aiobungie
A Pythonic async/await wrapper for interacting with the Bungie API.
Base client.
Example
import aiobungie
client = aiobungie.Client('YOUR_API_KEY')
# Search for Destiny2 users.
async def main() -> None:
async with client.rest:
users = await client.search_users('Crit')
# Iterate over the users and take the first 5 results.
for user in users.take(5):
print(f'{user.name} ({user.code})')
# Iterate through the users memberships.
for membership in user.memberships:
print(membership.type, membership.id)
client.run(main()) # or asyncio.run(main())
Single RESTClient instance.
The difference between base client and the REST clients:
- No Hight-Level concepts.
- All returned data are pure JSON objects from the API.
- No object creation.
Example
import aiobungie
async def main() -> None:
# Using `async with` context manager to close the session properly.
async with aiobungie.RESTClient("TOKEN") as rest:
payload = await rest.fetch_player('Fate怒', 4275)
for membership in payload:
print(membership['membershipId'], membership['iconPath'])
import asyncio
asyncio.run(main())
REST client pool.
A REST client pool allows you to acquire multiple RESTClient instances that shares the same connection.
Example
import aiobungie
import asyncio
pool = aiobungie.RESTPool("token")
async def func1() -> None:
async with pool.acquire() as instance:
tokens = await instance.fetch_oauth2_tokens('code')
pool.metadata['tokens'] = tokens
# Other instance may access the tokens from pool since its shared.
async def func2() -> None:
async with pool.acquire() as instance:
tokens = pool.metadata['tokens']
tokens = await instance.refresh_access_token(tokens.refresh_token)
async def main() -> None:
await asyncio.gather(func1(), func2())
asyncio.run(main())
Should you use the base client or the REST client? This returns to you. For an example if you're building a website.
You can use python as a REST API in the backend with the RESTClient since all returned object are JSON objects. Which gives you the freedom to deserialize it and implement your own logic in the front-end.
Or of you're building a Discord bot for an example or something simple. The base client is the way to go.
1# MIT License 2# 3# Copyright (c) 2020 - Present nxtlo 4# 5# Permission is hereby granted, free of charge, to any person obtaining a copy 6# of this software and associated documentation files (the "Software"), to deal 7# in the Software without restriction, including without limitation the rights 8# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9# copies of the Software, and to permit persons to whom the Software is 10# furnished to do so, subject to the following conditions: 11# 12# The above copyright notice and this permission notice shall be included in all 13# copies or substantial portions of the Software. 14# 15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21# SOFTWARE. 22 23"""A Pythonic `async`/`await` wrapper for interacting with the Bungie API. 24 25Base client. 26 27Example 28------- 29```py 30import aiobungie 31 32client = aiobungie.Client('YOUR_API_KEY') 33 34# Search for Destiny2 users. 35async def main() -> None: 36 async with client.rest: 37 users = await client.search_users('Crit') 38 39 # Iterate over the users and take the first 5 results. 40 for user in users.take(5): 41 print(f'{user.name} ({user.code})') 42 43 # Iterate through the users memberships. 44 for membership in user.memberships: 45 print(membership.type, membership.id) 46 47client.run(main()) # or asyncio.run(main()) 48``` 49 50Single RESTClient instance. 51 52The difference between base client and the REST clients: 53 54* No Hight-Level concepts. 55* All returned data are pure JSON objects from the API. 56* No object creation. 57 58Example 59------- 60```py 61import aiobungie 62 63async def main() -> None: 64 # Using `async with` context manager to close the session properly. 65 async with aiobungie.RESTClient("TOKEN") as rest: 66 payload = await rest.fetch_player('Fate怒', 4275) 67 68 for membership in payload: 69 print(membership['membershipId'], membership['iconPath']) 70 71import asyncio 72asyncio.run(main()) 73``` 74 75REST client pool. 76 77A REST client pool allows you to acquire multiple `RESTClient` instances that shares the same connection. 78 79Example 80------- 81```py 82import aiobungie 83import asyncio 84 85pool = aiobungie.RESTPool("token") 86 87async def func1() -> None: 88 async with pool.acquire() as instance: 89 tokens = await instance.fetch_oauth2_tokens('code') 90 pool.metadata['tokens'] = tokens 91 92# Other instance may access the tokens from pool since its shared. 93 94async def func2() -> None: 95 async with pool.acquire() as instance: 96 tokens = pool.metadata['tokens'] 97 tokens = await instance.refresh_access_token(tokens.refresh_token) 98 99async def main() -> None: 100 await asyncio.gather(func1(), func2()) 101 102asyncio.run(main()) 103``` 104 105Should you use the base client or the REST client? 106This returns to you. For an example if you're building a website. 107 108You can use python as a REST API in the backend with the RESTClient since all returned object are JSON objects. 109Which gives you the freedom to deserialize it and implement your own logic in the front-end. 110 111Or of you're building a Discord bot for an example or something simple. The base client is the way to go. 112""" 113 114 115from __future__ import annotations 116 117from aiobungie import builders 118from aiobungie import crates 119from aiobungie import interfaces 120from aiobungie import traits 121from aiobungie import typedefs 122from aiobungie import url 123from aiobungie.client import Client 124from aiobungie.error import * 125from aiobungie.internal import iterators 126from aiobungie.internal.assets import Image 127from aiobungie.internal.enums import * 128from aiobungie.internal.factory import Factory 129from aiobungie.internal.iterators import * 130from aiobungie.rest import * 131from aiobungie.undefined import UNDEFINED 132from aiobungie.undefined import UndefinedOr 133from aiobungie.undefined import UndefinedType 134 135from .metadata import __about__ 136from .metadata import __author__ 137from .metadata import __docs__ 138from .metadata import __email__ 139from .metadata import __license__ 140from .metadata import __url__ 141from .metadata import __version__ 142 143# Alias for crate for backwards compatibility. 144crate = crates 145 146# Activity enums 147from .crates.activity import Difficulty 148 149# Components enums 150from .crates.components import ComponentFields 151from .crates.components import ComponentPrivacy 152 153# Entity enums 154from .crates.entity import GatingScope 155from .crates.entity import ObjectiveUIStyle 156from .crates.entity import ValueUIStyle 157 158# Fireteam enums. 159from .crates.fireteams import FireteamActivity 160from .crates.fireteams import FireteamDate 161from .crates.fireteams import FireteamLanguage 162from .crates.fireteams import FireteamPlatform 163 164# Records enums 165from .crates.records import RecordState 166 167__all__ = [mod for mod in dir() if not mod.startswith("_")] # type: ignore
74@attrs.define(auto_exc=True) 75class AiobungieError(RuntimeError): 76 """Base class that all other exceptions inherit from."""
Base class that all other exceptions inherit from.
Inherited Members
- builtins.BaseException
- with_traceback
- args
635@typing.final 636class AmmoType(int, Enum): 637 """AN enum for Detyiny 2 ammo types.""" 638 639 NONE = 0 640 PRIMARY = 1 641 SPECIAL = 2 642 HEAVY = 3
AN enum for Detyiny 2 ammo types.
164@attrs.define(auto_exc=True) 165class BadRequest(HTTPError): 166 """An exception raised when requesting a resource with the provided data is wrong.""" 167 168 url: typing.Optional[typedefs.StrOrURL] 169 """The URL/endpoint caused this error.""" 170 171 body: typing.Any 172 """The response body.""" 173 174 headers: multidict.CIMultiDictProxy[str] 175 """The response headers.""" 176 177 http_status: http.HTTPStatus = attrs.field( 178 default=http.HTTPStatus.BAD_REQUEST, init=False 179 )
An exception raised when requesting a resource with the provided data is wrong.
2def __init__(self, message, url, body, headers): 3 self.message = message 4 self.url = url 5 self.body = body 6 self.headers = headers 7 self.http_status = attr_dict['http_status'].default 8 BaseException.__init__(self, self.message,self.url,self.body,self.headers)
Method generated by attrs for class BadRequest.
690@typing.final 691class ClanMemberType(int, Enum): 692 """An enum for bungie clan member types.""" 693 694 NONE = 0 695 BEGINNER = 1 696 MEMBER = 2 697 ADMIN = 3 698 ACTING_FOUNDER = 4 699 FOUNDER = 5
An enum for bungie clan member types.
466@typing.final 467class Class(int, Enum): 468 """An Enum for Destiny character classes.""" 469 470 TITAN = 0 471 HUNTER = 1 472 WARLOCK = 2 473 UNKNOWN = 3
An Enum for Destiny character classes.
60class Client(traits.ClientApp): 61 """Standard Bungie API client application. 62 63 This client deserialize the REST JSON responses using `aiobungie.internal.factory.Factory` 64 and returns `aiobungie.crates` Python object implementations of the responses. 65 66 A `aiobungie.RESTClient` REST client can also be used alone for low-level concepts. 67 68 Example 69 ------- 70 ```py 71 import aiobungie 72 73 client = aiobungie.Client('...') 74 75 async def main(): 76 async with client.rest: 77 user = await client.fetch_current_user_memberships('...') 78 print(user) 79 ``` 80 81 Parameters 82 ----------- 83 token: `str` 84 Your Bungie's API key or Token from the developer's portal. 85 86 Other Parameters 87 ---------------- 88 max_retries : `int` 89 The max retries number to retry if the request hit a `5xx` status code. 90 client_secret : `str | None` 91 An optional application client secret, 92 This is only needed if you're fetching OAuth2 tokens with this client. 93 client_id : `int | None` 94 An optional application client id, 95 This is only needed if you're fetching OAuth2 tokens with this client. 96 """ 97 98 __slots__ = ("_rest", "_factory") 99 100 def __init__( 101 self, 102 token: str, 103 /, 104 *, 105 client_secret: typing.Optional[str] = None, 106 client_id: typing.Optional[int] = None, 107 max_retries: int = 4, 108 ) -> None: 109 self._rest = rest_.RESTClient( 110 token, 111 client_secret=client_secret, 112 client_id=client_id, 113 max_retries=max_retries, 114 ) 115 116 self._factory = factory_.Factory(self) 117 118 @property 119 def factory(self) -> factory_.Factory: 120 return self._factory 121 122 @property 123 def rest(self) -> interfaces.RESTInterface: 124 return self._rest 125 126 @property 127 def request(self) -> Client: 128 return self 129 130 @property 131 def metadata(self) -> collections.MutableMapping[typing.Any, typing.Any]: 132 return self._rest.metadata 133 134 def run( 135 self, future: collections.Coroutine[typing.Any, None, None], debug: bool = False 136 ) -> None: 137 loop: typing.Final[asyncio.AbstractEventLoop] = helpers.get_or_make_loop() 138 try: 139 if not loop.is_running(): 140 loop.set_debug(debug) 141 loop.run_until_complete(future) 142 143 except Exception as exc: 144 raise RuntimeError(f"Failed to run {future.__qualname__}") from exc 145 146 except KeyboardInterrupt: 147 _LOG.warn("Unexpected Keyboard interrupt. Exiting.") 148 return 149 150 # * User methods. 151 152 async def fetch_current_user_memberships(self, access_token: str, /) -> user.User: 153 """Fetch and return a user object of the bungie net user associated with account. 154 155 .. warning:: 156 This method requires OAuth2 scope and a Bearer access token. 157 158 Parameters 159 ---------- 160 access_token : `str` 161 A valid Bearer access token for the authorization. 162 163 Returns 164 ------- 165 `aiobungie.crates.user.User` 166 A user object includes the Destiny memberships and Bungie.net user. 167 """ 168 resp = await self.rest.fetch_current_user_memberships(access_token) 169 170 return self.factory.deserialize_user(resp) 171 172 async def fetch_bungie_user(self, id: int, /) -> user.BungieUser: 173 """Fetch a Bungie user by their BungieNet id. 174 175 .. note:: 176 This returns a Bungie user membership only. Take a look at `Client.fetch_membership_from_id` 177 for other memberships. 178 179 Parameters 180 ---------- 181 id: `int` 182 The user id. 183 184 Returns 185 ------- 186 `aiobungie.crates.user.BungieUser` 187 A Bungie user. 188 189 Raises 190 ------ 191 `aiobungie.error.NotFound` 192 The user was not found. 193 """ 194 payload = await self.rest.fetch_bungie_user(id) 195 196 return self.factory.deserialize_bungie_user(payload) 197 198 async def search_users( 199 self, name: str, / 200 ) -> iterators.Iterator[user.SearchableDestinyUser]: 201 """Search for players and return all players that matches the same name. 202 203 Parameters 204 ---------- 205 name : `buildins.str` 206 The user name. 207 208 Returns 209 ------- 210 `aiobungie.iterators.Iterator[aiobungie.crates.DestinyMembership]` 211 A sequence of destiny memberships. 212 """ 213 payload = await self.rest.search_users(name) 214 215 return iterators.Iterator( 216 [ 217 self.factory.deserialize_searched_user(user) 218 for user in payload["searchResults"] 219 ] 220 ) 221 222 async def fetch_user_themes(self) -> collections.Sequence[user.UserThemes]: 223 """Fetch all available user themes. 224 225 Returns 226 ------- 227 `collections.Sequence[aiobungie.crates.user.UserThemes]` 228 A sequence of user themes. 229 """ 230 data = await self.rest.fetch_user_themes() 231 232 return self.factory.deserialize_user_themes(data) 233 234 async def fetch_hard_types( 235 self, 236 credential: int, 237 type: typedefs.IntAnd[enums.CredentialType] = enums.CredentialType.STEAMID, 238 /, 239 ) -> user.HardLinkedMembership: 240 """Gets any hard linked membership given a credential. 241 Only works for credentials that are public just `aiobungie.CredentialType.STEAMID` right now. 242 Cross Save aware. 243 244 Parameters 245 ---------- 246 credential: `int` 247 A valid SteamID64 248 type: `aiobungie.CredentialType` 249 The credential type. This must not be changed 250 Since its only credential that works "currently" 251 252 Returns 253 ------- 254 `aiobungie.crates.user.HardLinkedMembership` 255 Information about the hard linked data. 256 """ 257 258 payload = await self.rest.fetch_hardlinked_credentials(credential, type) 259 260 return user.HardLinkedMembership( 261 id=int(payload["membershipId"]), 262 type=enums.MembershipType(payload["membershipType"]), 263 cross_save_type=enums.MembershipType(payload["CrossSaveOverriddenType"]), 264 ) 265 266 async def fetch_membership_from_id( 267 self, 268 id: int, 269 /, 270 type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE, 271 ) -> user.User: 272 """Fetch Bungie user's memberships from their id. 273 274 Notes 275 ----- 276 * This returns both BungieNet membership and a sequence of the player's DestinyMemberships 277 Which includes Stadia, Xbox, Steam and PSN memberships if the player has them, 278 see `aiobungie.crates.user.DestinyMembership` for more details. 279 * If you only want the bungie user. Consider using `Client.fetch_user` method. 280 281 Parameters 282 ---------- 283 id : `int` 284 The user's id. 285 type : `aiobungie.MembershipType` 286 The user's membership type. 287 288 Returns 289 ------- 290 `aiobungie.crates.User` 291 A Bungie user with their membership types. 292 293 Raises 294 ------ 295 aiobungie.NotFound 296 The requested user was not found. 297 """ 298 payload = await self.rest.fetch_membership_from_id(id, type) 299 300 return self.factory.deserialize_user(payload) 301 302 async def fetch_user_credentials( 303 self, access_token: str, membership_id: int, / 304 ) -> collections.Sequence[user.UserCredentials]: 305 """Fetch an array of credential types attached to the requested account. 306 307 .. note:: 308 This method require OAuth2 Bearer access token. 309 310 Parameters 311 ---------- 312 access_token : `str` 313 The bearer access token associated with the bungie account. 314 membership_id : `int` 315 The id of the membership to return. 316 317 Returns 318 ------- 319 `collections.Sequence[aiobungie.crates.UserCredentials]` 320 A sequence of the attached user credentials. 321 322 Raises 323 ------ 324 `aiobungie.Unauthorized` 325 The access token was wrong or no access token passed. 326 """ 327 resp = await self.rest.fetch_user_credentials(access_token, membership_id) 328 329 return self.factory.deserialize_user_credentials(resp) 330 331 # * Destiny 2. 332 333 async def fetch_profile( 334 self, 335 member_id: int, 336 type: typedefs.IntAnd[enums.MembershipType], 337 components: list[enums.ComponentType], 338 auth: typing.Optional[str] = None, 339 ) -> components.Component: 340 """ 341 Fetch a bungie profile passing components to the request. 342 343 Parameters 344 ---------- 345 member_id: `int` 346 The member's id. 347 type: `aiobungie.MembershipType` 348 A valid membership type. 349 components : `list[aiobungie.ComponentType]` 350 List of profile components to collect and return. 351 352 Other Parameters 353 ---------------- 354 auth : `typing.Optional[str]` 355 A Bearer access_token to make the request with. 356 This is optional and limited to components that only requires an Authorization token. 357 358 Returns 359 -------- 360 `aiobungie.crates.Component` 361 A Destiny 2 player profile with its components. 362 Only passed components will be available if they exists. Otherwise they will be `None` 363 364 Raises 365 ------ 366 `aiobungie.MembershipTypeError` 367 The provided membership type was invalid. 368 """ 369 data = await self.rest.fetch_profile(member_id, type, components, auth) 370 return self.factory.deserialize_components(data) 371 372 async def fetch_linked_profiles( 373 self, 374 member_id: int, 375 member_type: typedefs.IntAnd[enums.MembershipType], 376 /, 377 *, 378 all: bool = False, 379 ) -> profile.LinkedProfile: 380 """Returns a summary information about all profiles linked to the requested member. 381 382 The passed membership id/type maybe a Bungie.Net membership or a Destiny memberships. 383 384 .. note:: 385 It will only return linked accounts whose linkages you are allowed to view. 386 387 Parameters 388 ---------- 389 member_id : `int` 390 The ID of the membership. This must be a valid Bungie.Net or PSN or Xbox ID. 391 member_type : `aiobungie.MembershipType` 392 The type for the membership whose linked Destiny account you want to return. 393 394 Other Parameters 395 ---------------- 396 all : `bool` 397 If provided and set to `True`, All memberships regardless 398 of whether they're obscured by overrides will be returned, 399 400 If provided and set to `False`, Only available memberships will be returned. 401 The default for this is `False`. 402 403 Returns 404 ------- 405 `aiobungie.crates.profile.LinkedProfile` 406 A linked profile object. 407 """ 408 resp = await self.rest.fetch_linked_profiles(member_id, member_type, all=all) 409 410 return self.factory.deserialize_linked_profiles(resp) 411 412 async def fetch_player( 413 self, 414 name: str, 415 code: int, 416 /, 417 type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.ALL, 418 ) -> collections.Sequence[user.DestinyMembership]: 419 """Fetch a Destiny 2 player's memberships. 420 421 Parameters 422 ----------- 423 name: `str` 424 The unique Bungie player name. 425 code : `int` 426 The unique Bungie display name code. 427 type: `aiobungie.internal.enums.MembershipType` 428 The player's membership type, e,g. XBOX, STEAM, PSN 429 430 Returns 431 -------- 432 `collections.Sequence[aiobungie.crates.DestinyMembership]` 433 A sequence of the found Destiny 2 player memberships. 434 An empty sequence will be returned if no one found. 435 436 Raises 437 ------ 438 `aiobungie.MembershipTypeError` 439 The provided membership type was invalid. 440 """ 441 resp = await self.rest.fetch_player(name, code, type) 442 443 return self.factory.deserialize_destiny_memberships(resp) 444 445 async def fetch_character( 446 self, 447 member_id: int, 448 membership_type: typedefs.IntAnd[enums.MembershipType], 449 character_id: int, 450 components: list[enums.ComponentType], 451 auth: typing.Optional[str] = None, 452 ) -> components.CharacterComponent: 453 """Fetch a Destiny 2 character. 454 455 Parameters 456 ---------- 457 member_id: `int` 458 A valid bungie member id. 459 character_id: `int` 460 The Destiny character id to retrieve. 461 membership_type: `aiobungie.internal.enums.MembershipType` 462 The member's membership type. 463 components: `list[aiobungie.ComponentType]` 464 Multiple arguments of character components to collect and return. 465 466 Other Parameters 467 ---------------- 468 auth : `typing.Optional[str]` 469 A Bearer access_token to make the request with. 470 This is optional and limited to components that only requires an Authorization token. 471 472 Returns 473 ------- 474 `aiobungie.crates.CharacterComponent` 475 A Bungie character component. 476 477 `aiobungie.MembershipTypeError` 478 The provided membership type was invalid. 479 """ 480 resp = await self.rest.fetch_character( 481 member_id, membership_type, character_id, components, auth 482 ) 483 484 return self.factory.deserialize_character_component(resp) 485 486 async def fetch_unique_weapon_history( 487 self, 488 membership_id: int, 489 character_id: int, 490 membership_type: typedefs.IntAnd[enums.MembershipType], 491 ) -> collections.Sequence[activity.ExtendedWeaponValues]: 492 """Fetch details about unique weapon usage for a character. Includes all exotics. 493 494 Parameters 495 ---------- 496 membership_id : `int` 497 The Destiny user membership id. 498 character_id : `int` 499 The character id to retrieve. 500 membership_type : `aiobungie.typedefs.IntAnd[aiobungie.MembershipType]` 501 The Destiny user's membership type. 502 503 Returns 504 ------- 505 `collections.Sequence[aiobungie.crates.ExtendedWeaponValues]` 506 A sequence of the weapon's extended values. 507 """ 508 resp = await self._rest.fetch_unique_weapon_history( 509 membership_id, character_id, membership_type 510 ) 511 512 return [ 513 self._factory.deserialize_extended_weapon_values(weapon) 514 for weapon in resp["weapons"] 515 ] 516 517 # * Destiny 2 Activities. 518 519 async def fetch_activities( 520 self, 521 member_id: int, 522 character_id: int, 523 mode: typedefs.IntAnd[enums.GameMode], 524 *, 525 membership_type: typedefs.IntAnd[ 526 enums.MembershipType 527 ] = enums.MembershipType.ALL, 528 page: int = 0, 529 limit: int = 250, 530 ) -> iterators.Iterator[activity.Activity]: 531 """Fetch a Destiny 2 activity for the specified character id. 532 533 Parameters 534 ---------- 535 member_id: `int` 536 The user id that starts with `4611`. 537 character_id: `int` 538 The id of the character to retrieve the activities for. 539 mode: `aiobungie.typedefs.IntAnd[aiobungie.internal.enums.GameMode]` 540 This parameter filters the game mode, Nightfall, Strike, Iron Banner, etc. 541 542 Other Parameters 543 ---------------- 544 membership_type: `aiobungie.internal.enums.MembershipType` 545 The Member ship type, if nothing was passed than it will return all. 546 page: int 547 The page number. Default is `0` 548 limit: int 549 Limit the returned result. Default is `250`. 550 551 Returns 552 ------- 553 `aiobungie.iterators.Iterator[aiobungie.crates.Activity]` 554 An iterator of the player's activities. 555 556 Raises 557 ------ 558 `aiobungie.MembershipTypeError` 559 The provided membership type was invalid. 560 """ 561 resp = await self.rest.fetch_activities( 562 member_id, 563 character_id, 564 mode, 565 membership_type=membership_type, 566 page=page, 567 limit=limit, 568 ) 569 570 return self.factory.deserialize_activities(resp) 571 572 async def fetch_post_activity(self, instance_id: int, /) -> activity.PostActivity: 573 """Fetch a post activity details. 574 575 Parameters 576 ---------- 577 instance_id: `int` 578 The activity instance id. 579 580 Returns 581 ------- 582 `aiobungie.crates.PostActivity` 583 A post activity object. 584 """ 585 resp = await self.rest.fetch_post_activity(instance_id) 586 587 return self.factory.deserialize_post_activity(resp) 588 589 async def fetch_aggregated_activity_stats( 590 self, 591 character_id: int, 592 membership_id: int, 593 membership_type: typedefs.IntAnd[enums.MembershipType], 594 ) -> iterators.Iterator[activity.AggregatedActivity]: 595 """Fetch aggregated activity stats for a character. 596 597 Parameters 598 ---------- 599 character_id: `int` 600 The id of the character to retrieve the activities for. 601 membership_id: `int` 602 The id of the user that started with `4611`. 603 membership_type: `aiobungie.internal.enums.MembershipType` 604 The Member ship type. 605 606 Returns 607 ------- 608 `aiobungie.iterators.Iterator[aiobungie.crates.AggregatedActivity]` 609 An iterator of the player's activities. 610 611 Raises 612 ------ 613 `aiobungie.MembershipTypeError` 614 The provided membership type was invalid. 615 """ 616 resp = await self.rest.fetch_aggregated_activity_stats( 617 character_id, membership_id, membership_type 618 ) 619 620 return self.factory.deserialize_aggregated_activities(resp) 621 622 # * Destiny 2 Clans or GroupsV2. 623 624 async def fetch_clan_from_id( 625 self, 626 id: int, 627 /, 628 access_token: typing.Optional[str] = None, 629 ) -> clans.Clan: 630 """Fetch a Bungie Clan by its id. 631 632 Parameters 633 ----------- 634 id: `int` 635 The clan id. 636 637 Returns 638 -------- 639 `aiobungie.crates.Clan` 640 An Bungie clan. 641 642 Raises 643 ------ 644 `aiobungie.NotFound` 645 The clan was not found. 646 """ 647 resp = await self.rest.fetch_clan_from_id(id, access_token) 648 649 return self.factory.deserialize_clan(resp) 650 651 async def fetch_clan( 652 self, 653 name: str, 654 /, 655 access_token: typing.Optional[str] = None, 656 *, 657 type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN, 658 ) -> clans.Clan: 659 """Fetch a Clan by its name. 660 This method will return the first clan found with given name. 661 662 Parameters 663 ---------- 664 name: `str` 665 The clan name 666 667 Other Parameters 668 ---------------- 669 access_token : `typing.Optional[str]` 670 An optional access token to make the request with. 671 672 If the token was bound to a member of the clan, 673 This field `aiobungie.crates.Clan.current_user_membership` will be available 674 and will return the membership of the user who made this request. 675 type : `aiobungie.GroupType` 676 The group type, Default is aiobungie.GroupType.CLAN. 677 678 Returns 679 ------- 680 `aiobungie.crates.Clan` 681 A Bungie clan. 682 683 Raises 684 ------ 685 `aiobungie.NotFound` 686 The clan was not found. 687 """ 688 resp = await self.rest.fetch_clan(name, access_token, type=type) 689 690 return self.factory.deserialize_clan(resp) 691 692 async def fetch_clan_conversations( 693 self, clan_id: int, / 694 ) -> collections.Sequence[clans.ClanConversation]: 695 """Fetch the conversations/chat channels of the given clan id. 696 697 Parameters 698 ---------- 699 clan_id : `int` 700 The clan id. 701 702 Returns 703 `collections.Sequence[aiobungie.crates.ClanConversation]` 704 A sequence of the clan chat channels. 705 """ 706 resp = await self.rest.fetch_clan_conversations(clan_id) 707 708 return self.factory.deserialize_clan_conversations(resp) 709 710 async def fetch_clan_admins( 711 self, clan_id: int, / 712 ) -> iterators.Iterator[clans.ClanMember]: 713 """Fetch the clan founder and admins. 714 715 Parameters 716 ---------- 717 clan_id : `int` 718 The clan id. 719 720 Returns 721 ------- 722 `aiobungie.iterators.Iterator[aiobungie.crates.ClanMember]` 723 An iterator over the found clan admins and founder. 724 725 Raises 726 ------ 727 `aiobungie.NotFound` 728 The requested clan was not found. 729 """ 730 resp = await self.rest.fetch_clan_admins(clan_id) 731 732 return self.factory.deserialize_clan_members(resp) 733 734 async def fetch_groups_for_member( 735 self, 736 member_id: int, 737 member_type: typedefs.IntAnd[enums.MembershipType], 738 /, 739 *, 740 filter: int = 0, 741 group_type: enums.GroupType = enums.GroupType.CLAN, 742 ) -> collections.Sequence[clans.GroupMember]: 743 """Fetch information about the groups that a given member has joined. 744 745 Parameters 746 ---------- 747 member_id : `int` 748 The member's id 749 member_type : `aiobungie.MembershipType` 750 The member's membership type. 751 752 Other Parameters 753 ---------------- 754 filter : `int` 755 Filter apply to list of joined groups. This Default to `0` 756 group_type : `aiobungie.GroupType` 757 The group's type. 758 This is always set to `aiobungie.GroupType.CLAN` and should not be changed. 759 760 Returns 761 ------- 762 `collections.Sequence[aiobungie.crates.GroupMember]` 763 A sequence of joined groups for the fetched member. 764 """ 765 resp = await self.rest.fetch_groups_for_member( 766 member_id, member_type, filter=filter, group_type=group_type 767 ) 768 769 return [ 770 self.factory.deserialize_group_member(group) for group in resp["results"] 771 ] 772 773 async def fetch_potential_groups_for_member( 774 self, 775 member_id: int, 776 member_type: typedefs.IntAnd[enums.MembershipType], 777 /, 778 *, 779 filter: int = 0, 780 group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN, 781 ) -> collections.Sequence[clans.GroupMember]: 782 """Fetch the potential groups for a clan member. 783 784 Parameters 785 ---------- 786 member_id : `int` 787 The member's id 788 member_type : `aiobungie.typedefs.IntAnd[aiobungie.MembershipType]` 789 The member's membership type. 790 791 Other Parameters 792 ---------------- 793 filter : `int` 794 Filter apply to list of joined groups. This Default to `0` 795 group_type : `aiobungie.typedefs.IntAnd[aiobungie.GroupType]` 796 The group's type. 797 This is always set to `aiobungie.GroupType.CLAN` and should not be changed. 798 799 Returns 800 ------- 801 `collections.Sequence[aiobungie.crates.GroupMember]` 802 A sequence of joined potential groups for the fetched member. 803 """ 804 resp = await self.rest.fetch_potential_groups_for_member( 805 member_id, member_type, filter=filter, group_type=group_type 806 ) 807 808 return [ 809 self.factory.deserialize_group_member(group) for group in resp["results"] 810 ] 811 812 async def fetch_clan_members( 813 self, 814 clan_id: int, 815 /, 816 *, 817 name: typing.Optional[str] = None, 818 type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE, 819 ) -> iterators.Iterator[clans.ClanMember]: 820 """Fetch Bungie clan members. 821 822 Parameters 823 ---------- 824 clan_id : `int` 825 The clans id 826 827 Other Parameters 828 ---------------- 829 name : `typing.Optional[str]` 830 If provided, Only players matching this name will be returned. 831 type : `aiobungie.MembershipType` 832 An optional clan member's membership type. 833 This parameter is used to filter the returned results 834 by the provided membership, For an example XBox memberships only, 835 Otherwise will return all memberships. 836 837 Returns 838 ------- 839 `aiobungie.iterators.Iterator[aiobungie.crates.ClanMember]` 840 An iterator over the bungie clan members. 841 842 Raises 843 ------ 844 `aiobungie.NotFound` 845 The clan was not found. 846 """ 847 resp = await self.rest.fetch_clan_members(clan_id, type=type, name=name) 848 849 return self.factory.deserialize_clan_members(resp) 850 851 async def fetch_clan_banners(self) -> collections.Sequence[clans.ClanBanner]: 852 """Fetch the clan banners. 853 854 Returns 855 ------- 856 `collections.Sequence[aiobungie.crates.ClanBanner]` 857 A sequence of the clan banners. 858 """ 859 resp = await self.rest.fetch_clan_banners() 860 861 return self.factory.deserialize_clan_banners(resp) 862 863 # This method is required to be here since it deserialize the clan. 864 async def kick_clan_member( 865 self, 866 access_token: str, 867 /, 868 group_id: int, 869 membership_id: int, 870 membership_type: typedefs.IntAnd[enums.MembershipType], 871 ) -> clans.Clan: 872 """Kick a member from the clan. 873 874 .. note:: 875 This request requires OAuth2: oauth2: `AdminGroups` scope. 876 877 Parameters 878 ---------- 879 access_token : `str` 880 The bearer access token associated with the bungie account. 881 group_id: `int` 882 The group id. 883 membership_id : `int` 884 The member id to kick. 885 membership_type : `aiobungie.typedefs.IntAnd[aiobungie.MembershipType]` 886 The member's membership type. 887 888 Returns 889 ------- 890 `aiobungie.crates.clan.Clan` 891 The clan that the member was kicked from. 892 """ 893 resp = await self.rest.kick_clan_member( 894 access_token, 895 group_id=group_id, 896 membership_id=membership_id, 897 membership_type=membership_type, 898 ) 899 900 return self.factory.deserialize_clan(resp) 901 902 async def fetch_clan_weekly_rewards(self, clan_id: int) -> milestones.Milestone: 903 """Fetch a Bungie clan's weekly reward state. 904 905 Parameters 906 ---------- 907 clan_id : `int` 908 The clan's id. 909 910 Returns 911 ------- 912 `aiobungie.crates.Milestone` 913 A runtime status of the clan's milestone data. 914 """ 915 916 resp = await self.rest.fetch_clan_weekly_rewards(clan_id) 917 918 return self.factory.deserialize_milestone(resp) 919 920 # * Destiny 2 Entities aka Definitions. 921 922 async def fetch_inventory_item(self, hash: int, /) -> entity.InventoryEntity: 923 """Fetch a static inventory item entity given a its hash. 924 925 Parameters 926 ---------- 927 hash: `int` 928 Inventory item's hash. 929 930 Returns 931 ------- 932 `aiobungie.crates.InventoryEntity` 933 A bungie inventory item. 934 """ 935 resp = await self.rest.fetch_inventory_item(hash) 936 937 return self.factory.deserialize_inventory_entity(resp) 938 939 async def fetch_objective_entity(self, hash: int, /) -> entity.ObjectiveEntity: 940 """Fetch a Destiny objective entity given a its hash. 941 942 Parameters 943 ---------- 944 hash: `int` 945 objective's hash. 946 947 Returns 948 ------- 949 `aiobungie.crates.ObjectiveEntity` 950 An objective entity item. 951 """ 952 resp = await self.rest.fetch_objective_entity(hash) 953 954 return self.factory.deserialize_objective_entity(resp) 955 956 async def search_entities( 957 self, name: str, entity_type: str, *, page: int = 0 958 ) -> iterators.Iterator[entity.SearchableEntity]: 959 """Search for Destiny2 entities given a name and its type. 960 961 Parameters 962 ---------- 963 name : `str` 964 The name of the entity, i.e., Thunderlord, One thousand voices. 965 entity_type : `str` 966 The type of the entity, AKA Definition, 967 For an example `DestinyInventoryItemDefinition` for emblems, weapons, and other inventory items. 968 969 Other Parameters 970 ---------------- 971 page : `int` 972 An optional page to return. Default to 0. 973 974 Returns 975 ------- 976 `aiobungie.iterators.Iterator[aiobungie.crates.SearchableEntity]` 977 An iterator over the found results matching the provided name. 978 """ 979 resp = await self.rest.search_entities(name, entity_type, page=page) 980 981 return self.factory.deserialize_inventory_results(resp) 982 983 # Fireteams 984 985 async def fetch_fireteams( 986 self, 987 activity_type: typedefs.IntAnd[fireteams.FireteamActivity], 988 *, 989 platform: typedefs.IntAnd[ 990 fireteams.FireteamPlatform 991 ] = fireteams.FireteamPlatform.ANY, 992 language: typing.Union[ 993 fireteams.FireteamLanguage, str 994 ] = fireteams.FireteamLanguage.ALL, 995 date_range: int = 0, 996 page: int = 0, 997 slots_filter: int = 0, 998 ) -> typing.Optional[collections.Sequence[fireteams.Fireteam]]: 999 """Fetch public Bungie fireteams with open slots. 1000 1001 Parameters 1002 ---------- 1003 activity_type : `aiobungie.typedefs.IntAnd[aiobungie.crates.FireteamActivity]` 1004 The fireteam activity type. 1005 1006 Other Parameters 1007 ---------------- 1008 platform : `aiobungie.typedefs.IntAnd[aiobungie.crates.fireteams.FireteamPlatform]` 1009 If this is provided. Then the results will be filtered with the given platform. 1010 Defaults to `aiobungie.crates.FireteamPlatform.ANY` which returns all platforms. 1011 language : `typing.Union[aiobungie.crates.fireteams.FireteamLanguage, str]` 1012 A locale language to filter the used language in that fireteam. 1013 Defaults to `aiobungie.crates.FireteamLanguage.ALL` 1014 date_range : `int` 1015 An integer to filter the date range of the returned fireteams. Defaults to `aiobungie.FireteamDate.ALL`. 1016 page : `int` 1017 The page number. By default its `0` which returns all available activities. 1018 slots_filter : `int` 1019 Filter the returned fireteams based on available slots. Default is `0` 1020 1021 Returns 1022 ------- 1023 `typing.Optional[collections.Sequence[fireteams.Fireteam]]` 1024 A sequence of `aiobungie.crates.Fireteam` or `None`. 1025 """ 1026 1027 resp = await self.rest.fetch_fireteams( 1028 activity_type, 1029 platform=platform, 1030 language=language, 1031 date_range=date_range, 1032 page=page, 1033 slots_filter=slots_filter, 1034 ) 1035 1036 return self.factory.deserialize_fireteams(resp) 1037 1038 async def fetch_avaliable_clan_fireteams( 1039 self, 1040 access_token: str, 1041 group_id: int, 1042 activity_type: typedefs.IntAnd[fireteams.FireteamActivity], 1043 *, 1044 platform: typedefs.IntAnd[fireteams.FireteamPlatform], 1045 language: typing.Union[fireteams.FireteamLanguage, str], 1046 date_range: int = 0, 1047 page: int = 0, 1048 public_only: bool = False, 1049 slots_filter: int = 0, 1050 ) -> typing.Optional[collections.Sequence[fireteams.Fireteam]]: 1051 """Fetch a clan's fireteams with open slots. 1052 1053 .. note:: 1054 This method requires OAuth2: ReadGroups scope. 1055 1056 Parameters 1057 ---------- 1058 access_token : `str` 1059 The bearer access token associated with the bungie account. 1060 group_id : `int` 1061 The group/clan id of the fireteam. 1062 activity_type : `aiobungie.typedefs.IntAnd[aiobungie.crates.FireteamActivity]` 1063 The fireteam activity type. 1064 1065 Other Parameters 1066 ---------------- 1067 platform : `aiobungie.typedefs.IntAnd[aiobungie.crates.fireteams.FireteamPlatform]` 1068 If this is provided. Then the results will be filtered with the given platform. 1069 Defaults to `aiobungie.crates.FireteamPlatform.ANY` which returns all platforms. 1070 language : `typing.Union[aiobungie.crates.fireteams.FireteamLanguage, str]` 1071 A locale language to filter the used language in that fireteam. 1072 Defaults to `aiobungie.crates.FireteamLanguage.ALL` 1073 date_range : `int` 1074 An integer to filter the date range of the returned fireteams. Defaults to `0`. 1075 page : `int` 1076 The page number. By default its `0` which returns all available activities. 1077 public_only: `bool` 1078 If set to True, Then only public fireteams will be returned. 1079 slots_filter : `int` 1080 Filter the returned fireteams based on available slots. Default is `0` 1081 1082 Returns 1083 ------- 1084 `typing.Optional[collections.Sequence[aiobungie.crates.Fireteam]]` 1085 A sequence of fireteams found in the clan. 1086 `None` will be returned if nothing was found. 1087 """ 1088 resp = await self.rest.fetch_avaliable_clan_fireteams( 1089 access_token, 1090 group_id, 1091 activity_type, 1092 platform=platform, 1093 language=language, 1094 date_range=date_range, 1095 page=page, 1096 public_only=public_only, 1097 slots_filter=slots_filter, 1098 ) 1099 1100 return self.factory.deserialize_fireteams(resp) 1101 1102 async def fetch_clan_fireteam( 1103 self, access_token: str, fireteam_id: int, group_id: int 1104 ) -> fireteams.AvailableFireteam: 1105 """Fetch a specific clan fireteam. 1106 1107 .. note:: 1108 This method requires OAuth2: ReadGroups scope. 1109 1110 Parameters 1111 ---------- 1112 access_token : `str` 1113 The bearer access token associated with the bungie account. 1114 group_id : `int` 1115 The group/clan id to fetch the fireteam from. 1116 fireteam_id : `int` 1117 The fireteam id to fetch. 1118 1119 Returns 1120 ------- 1121 `typing.Optional[aiobungie.crates.AvailableFireteam]` 1122 A sequence of available fireteams objects if exists. else `None` will be returned. 1123 """ 1124 resp = await self.rest.fetch_clan_fireteam(access_token, fireteam_id, group_id) 1125 1126 return self.factory.deserialize_available_fireteams( 1127 resp, no_results=True 1128 ) # type: ignore[return-value] 1129 1130 async def fetch_my_clan_fireteams( 1131 self, 1132 access_token: str, 1133 group_id: int, 1134 *, 1135 include_closed: bool = True, 1136 platform: typedefs.IntAnd[fireteams.FireteamPlatform], 1137 language: typing.Union[fireteams.FireteamLanguage, str], 1138 filtered: bool = True, 1139 page: int = 0, 1140 ) -> collections.Sequence[fireteams.AvailableFireteam]: 1141 """A method that's similar to `fetch_fireteams` but requires OAuth2. 1142 1143 .. note:: 1144 This method requires OAuth2: ReadGroups scope. 1145 1146 Parameters 1147 ---------- 1148 access_token : str 1149 The bearer access token associated with the bungie account. 1150 group_id : int 1151 The group/clan id to fetch. 1152 1153 Other Parameters 1154 ---------------- 1155 include_closed : bool 1156 If provided and set to True, It will also return closed fireteams. 1157 If provided and set to False, It will only return public fireteams. Default is True. 1158 platform : aiobungie.typedefs.IntAnd[aiobungie.crates.fireteams.FireteamPlatform] 1159 If this is provided. Then the results will be filtered with the given platform. 1160 Defaults to aiobungie.crates.FireteamPlatform.ANY which returns all platforms. 1161 language : typing.Union[aiobungie.crates.fireteams.FireteamLanguage, str] 1162 A locale language to filter the used language in that fireteam. 1163 Defaults to aiobungie.crates.FireteamLanguage.ALL 1164 filtered : bool 1165 If set to True, it will filter by clan. Otherwise not. Default is True. 1166 page : int 1167 The page number. By default its 0 which returns all available activities. 1168 1169 Returns 1170 ------- 1171 `collections.Sequence[aiobungie.crates.AvailableFireteam]` 1172 A sequence of available fireteams objects if exists. else `None` will be returned. 1173 """ 1174 resp = await self.rest.fetch_my_clan_fireteams( 1175 access_token, 1176 group_id, 1177 include_closed=include_closed, 1178 platform=platform, 1179 language=language, 1180 filtered=filtered, 1181 page=page, 1182 ) 1183 1184 return self.factory.deserialize_available_fireteams(resp) # type: ignore[return-value] 1185 1186 # Friends and social. 1187 1188 async def fetch_friends( 1189 self, access_token: str, / 1190 ) -> collections.Sequence[friends.Friend]: 1191 """Fetch bungie friend list. 1192 1193 .. note:: 1194 This requests OAuth2: ReadUserData scope. 1195 1196 Parameters 1197 ----------- 1198 access_token : `str` 1199 The bearer access token associated with the bungie account. 1200 1201 Returns 1202 ------- 1203 `collections.Sequence[aiobungie.crates.Friend]` 1204 A sequence of the friends associated with that access token. 1205 """ 1206 1207 resp = await self.rest.fetch_friends(access_token) 1208 1209 return self.factory.deserialize_friends(resp) 1210 1211 async def fetch_friend_requests( 1212 self, access_token: str, / 1213 ) -> friends.FriendRequestView: 1214 """Fetch pending bungie friend requests queue. 1215 1216 .. note:: 1217 This requests OAuth2: ReadUserData scope. 1218 1219 Parameters 1220 ----------- 1221 access_token : `str` 1222 The bearer access token associated with the bungie account. 1223 1224 Returns 1225 ------- 1226 `aiobungie.crates.FriendRequestView` 1227 A friend requests view of that associated access token. 1228 """ 1229 1230 resp = await self.rest.fetch_friend_requests(access_token) 1231 1232 return self.factory.deserialize_friend_requests(resp) 1233 1234 # Applications and Developer portal. 1235 1236 async def fetch_application(self, appid: int, /) -> application.Application: 1237 """Fetch a Bungie application. 1238 1239 Parameters 1240 ----------- 1241 appid: `int` 1242 The application id. 1243 1244 Returns 1245 -------- 1246 `aiobungie.crates.Application` 1247 A Bungie application. 1248 """ 1249 resp = await self.rest.fetch_application(appid) 1250 1251 return self.factory.deserialize_app(resp) 1252 1253 # Milestones 1254 1255 async def fetch_public_milestone_content( 1256 self, milestone_hash: int, / 1257 ) -> milestones.MilestoneContent: 1258 """Fetch the milestone content given its hash. 1259 1260 Parameters 1261 ---------- 1262 milestone_hash : `int` 1263 The milestone hash. 1264 1265 Returns 1266 ------- 1267 `aiobungie.crates.milestones.MilestoneContent` 1268 A milestone content object. 1269 """ 1270 resp = await self.rest.fetch_public_milestone_content(milestone_hash) 1271 1272 return self.factory.deserialize_public_milestone_content(resp)
Standard Bungie API client application.
This client deserialize the REST JSON responses using Factory
and returns aiobungie.crates Python object implementations of the responses.
A aiobungie.RESTClient REST client can also be used alone for low-level concepts.
Example
import aiobungie
client = aiobungie.Client('...')
async def main():
async with client.rest:
user = await client.fetch_current_user_memberships('...')
print(user)
Parameters
- token (
str): Your Bungie's API key or Token from the developer's portal.
Other Parameters
- max_retries (
int): The max retries number to retry if the request hit a5xxstatus code. - client_secret (
str | None): An optional application client secret, This is only needed if you're fetching OAuth2 tokens with this client. - client_id (
int | None): An optional application client id, This is only needed if you're fetching OAuth2 tokens with this client.
100 def __init__( 101 self, 102 token: str, 103 /, 104 *, 105 client_secret: typing.Optional[str] = None, 106 client_id: typing.Optional[int] = None, 107 max_retries: int = 4, 108 ) -> None: 109 self._rest = rest_.RESTClient( 110 token, 111 client_secret=client_secret, 112 client_id=client_id, 113 max_retries=max_retries, 114 ) 115 116 self._factory = factory_.Factory(self)
A mutable mapping storage for the user's needs.
134 def run( 135 self, future: collections.Coroutine[typing.Any, None, None], debug: bool = False 136 ) -> None: 137 loop: typing.Final[asyncio.AbstractEventLoop] = helpers.get_or_make_loop() 138 try: 139 if not loop.is_running(): 140 loop.set_debug(debug) 141 loop.run_until_complete(future) 142 143 except Exception as exc: 144 raise RuntimeError(f"Failed to run {future.__qualname__}") from exc 145 146 except KeyboardInterrupt: 147 _LOG.warn("Unexpected Keyboard interrupt. Exiting.") 148 return
Runs a coroutine function until its complete.
This is equivalent to asyncio.get_event_loop().run_until_complete(...)
Parameters
- future (
collections.Coroutine[None, None, None]): A coroutine object. - debug (
bool): Either to enable asyncio debug or not. Disabled by default.
Example
async def main() -> None:
await fetch(...)
# Run the coroutine.
client.run(main())
152 async def fetch_current_user_memberships(self, access_token: str, /) -> user.User: 153 """Fetch and return a user object of the bungie net user associated with account. 154 155 .. warning:: 156 This method requires OAuth2 scope and a Bearer access token. 157 158 Parameters 159 ---------- 160 access_token : `str` 161 A valid Bearer access token for the authorization. 162 163 Returns 164 ------- 165 `aiobungie.crates.user.User` 166 A user object includes the Destiny memberships and Bungie.net user. 167 """ 168 resp = await self.rest.fetch_current_user_memberships(access_token) 169 170 return self.factory.deserialize_user(resp)
Fetch and return a user object of the bungie net user associated with account.
This method requires OAuth2 scope and a Bearer access token.
Parameters
- access_token (
str): A valid Bearer access token for the authorization.
Returns
aiobungie.crates.user.User: A user object includes the Destiny memberships and Bungie.net user.
172 async def fetch_bungie_user(self, id: int, /) -> user.BungieUser: 173 """Fetch a Bungie user by their BungieNet id. 174 175 .. note:: 176 This returns a Bungie user membership only. Take a look at `Client.fetch_membership_from_id` 177 for other memberships. 178 179 Parameters 180 ---------- 181 id: `int` 182 The user id. 183 184 Returns 185 ------- 186 `aiobungie.crates.user.BungieUser` 187 A Bungie user. 188 189 Raises 190 ------ 191 `aiobungie.error.NotFound` 192 The user was not found. 193 """ 194 payload = await self.rest.fetch_bungie_user(id) 195 196 return self.factory.deserialize_bungie_user(payload)
Fetch a Bungie user by their BungieNet id.
This returns a Bungie user membership only. Take a look at Client.fetch_membership_from_id
for other memberships.
Parameters
- id (
int): The user id.
Returns
aiobungie.crates.user.BungieUser: A Bungie user.
Raises
NotFound: The user was not found.
198 async def search_users( 199 self, name: str, / 200 ) -> iterators.Iterator[user.SearchableDestinyUser]: 201 """Search for players and return all players that matches the same name. 202 203 Parameters 204 ---------- 205 name : `buildins.str` 206 The user name. 207 208 Returns 209 ------- 210 `aiobungie.iterators.Iterator[aiobungie.crates.DestinyMembership]` 211 A sequence of destiny memberships. 212 """ 213 payload = await self.rest.search_users(name) 214 215 return iterators.Iterator( 216 [ 217 self.factory.deserialize_searched_user(user) 218 for user in payload["searchResults"] 219 ] 220 )
Search for players and return all players that matches the same name.
Parameters
- name (
buildins.str): The user name.
Returns
aiobungie.iterators.Iterator[aiobungie.crates.DestinyMembership]: A sequence of destiny memberships.
222 async def fetch_user_themes(self) -> collections.Sequence[user.UserThemes]: 223 """Fetch all available user themes. 224 225 Returns 226 ------- 227 `collections.Sequence[aiobungie.crates.user.UserThemes]` 228 A sequence of user themes. 229 """ 230 data = await self.rest.fetch_user_themes() 231 232 return self.factory.deserialize_user_themes(data)
Fetch all available user themes.
Returns
collections.Sequence[aiobungie.crates.user.UserThemes]: A sequence of user themes.
234 async def fetch_hard_types( 235 self, 236 credential: int, 237 type: typedefs.IntAnd[enums.CredentialType] = enums.CredentialType.STEAMID, 238 /, 239 ) -> user.HardLinkedMembership: 240 """Gets any hard linked membership given a credential. 241 Only works for credentials that are public just `aiobungie.CredentialType.STEAMID` right now. 242 Cross Save aware. 243 244 Parameters 245 ---------- 246 credential: `int` 247 A valid SteamID64 248 type: `aiobungie.CredentialType` 249 The credential type. This must not be changed 250 Since its only credential that works "currently" 251 252 Returns 253 ------- 254 `aiobungie.crates.user.HardLinkedMembership` 255 Information about the hard linked data. 256 """ 257 258 payload = await self.rest.fetch_hardlinked_credentials(credential, type) 259 260 return user.HardLinkedMembership( 261 id=int(payload["membershipId"]), 262 type=enums.MembershipType(payload["membershipType"]), 263 cross_save_type=enums.MembershipType(payload["CrossSaveOverriddenType"]), 264 )
Gets any hard linked membership given a credential.
Only works for credentials that are public just aiobungie.CredentialType.STEAMID right now.
Cross Save aware.
Parameters
- credential (
int): A valid SteamID64 - type (
aiobungie.CredentialType): The credential type. This must not be changed Since its only credential that works "currently"
Returns
aiobungie.crates.user.HardLinkedMembership: Information about the hard linked data.
266 async def fetch_membership_from_id( 267 self, 268 id: int, 269 /, 270 type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE, 271 ) -> user.User: 272 """Fetch Bungie user's memberships from their id. 273 274 Notes 275 ----- 276 * This returns both BungieNet membership and a sequence of the player's DestinyMemberships 277 Which includes Stadia, Xbox, Steam and PSN memberships if the player has them, 278 see `aiobungie.crates.user.DestinyMembership` for more details. 279 * If you only want the bungie user. Consider using `Client.fetch_user` method. 280 281 Parameters 282 ---------- 283 id : `int` 284 The user's id. 285 type : `aiobungie.MembershipType` 286 The user's membership type. 287 288 Returns 289 ------- 290 `aiobungie.crates.User` 291 A Bungie user with their membership types. 292 293 Raises 294 ------ 295 aiobungie.NotFound 296 The requested user was not found. 297 """ 298 payload = await self.rest.fetch_membership_from_id(id, type) 299 300 return self.factory.deserialize_user(payload)
Fetch Bungie user's memberships from their id.
Notes
- This returns both BungieNet membership and a sequence of the player's DestinyMemberships
Which includes Stadia, Xbox, Steam and PSN memberships if the player has them,
see
aiobungie.crates.user.DestinyMembershipfor more details. - If you only want the bungie user. Consider using
Client.fetch_usermethod.
Parameters
- id (
int): The user's id. - type (
aiobungie.MembershipType): The user's membership type.
Returns
aiobungie.crates.User: A Bungie user with their membership types.
Raises
- aiobungie.NotFound: The requested user was not found.
302 async def fetch_user_credentials( 303 self, access_token: str, membership_id: int, / 304 ) -> collections.Sequence[user.UserCredentials]: 305 """Fetch an array of credential types attached to the requested account. 306 307 .. note:: 308 This method require OAuth2 Bearer access token. 309 310 Parameters 311 ---------- 312 access_token : `str` 313 The bearer access token associated with the bungie account. 314 membership_id : `int` 315 The id of the membership to return. 316 317 Returns 318 ------- 319 `collections.Sequence[aiobungie.crates.UserCredentials]` 320 A sequence of the attached user credentials. 321 322 Raises 323 ------ 324 `aiobungie.Unauthorized` 325 The access token was wrong or no access token passed. 326 """ 327 resp = await self.rest.fetch_user_credentials(access_token, membership_id) 328 329 return self.factory.deserialize_user_credentials(resp)
Fetch an array of credential types attached to the requested account.
This method require OAuth2 Bearer access token.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - membership_id (
int): The id of the membership to return.
Returns
collections.Sequence[aiobungie.crates.UserCredentials]: A sequence of the attached user credentials.
Raises
aiobungie.Unauthorized: The access token was wrong or no access token passed.
333 async def fetch_profile( 334 self, 335 member_id: int, 336 type: typedefs.IntAnd[enums.MembershipType], 337 components: list[enums.ComponentType], 338 auth: typing.Optional[str] = None, 339 ) -> components.Component: 340 """ 341 Fetch a bungie profile passing components to the request. 342 343 Parameters 344 ---------- 345 member_id: `int` 346 The member's id. 347 type: `aiobungie.MembershipType` 348 A valid membership type. 349 components : `list[aiobungie.ComponentType]` 350 List of profile components to collect and return. 351 352 Other Parameters 353 ---------------- 354 auth : `typing.Optional[str]` 355 A Bearer access_token to make the request with. 356 This is optional and limited to components that only requires an Authorization token. 357 358 Returns 359 -------- 360 `aiobungie.crates.Component` 361 A Destiny 2 player profile with its components. 362 Only passed components will be available if they exists. Otherwise they will be `None` 363 364 Raises 365 ------ 366 `aiobungie.MembershipTypeError` 367 The provided membership type was invalid. 368 """ 369 data = await self.rest.fetch_profile(member_id, type, components, auth) 370 return self.factory.deserialize_components(data)
Fetch a bungie profile passing components to the request.
Parameters
- member_id (
int): The member's id. - type (
aiobungie.MembershipType): A valid membership type. - components (
list[aiobungie.ComponentType]): List of profile components to collect and return.
Other Parameters
- auth (
typing.Optional[str]): A Bearer access_token to make the request with. This is optional and limited to components that only requires an Authorization token.
Returns
aiobungie.crates.Component: A Destiny 2 player profile with its components. Only passed components will be available if they exists. Otherwise they will beNone
Raises
aiobungie.MembershipTypeError: The provided membership type was invalid.
372 async def fetch_linked_profiles( 373 self, 374 member_id: int, 375 member_type: typedefs.IntAnd[enums.MembershipType], 376 /, 377 *, 378 all: bool = False, 379 ) -> profile.LinkedProfile: 380 """Returns a summary information about all profiles linked to the requested member. 381 382 The passed membership id/type maybe a Bungie.Net membership or a Destiny memberships. 383 384 .. note:: 385 It will only return linked accounts whose linkages you are allowed to view. 386 387 Parameters 388 ---------- 389 member_id : `int` 390 The ID of the membership. This must be a valid Bungie.Net or PSN or Xbox ID. 391 member_type : `aiobungie.MembershipType` 392 The type for the membership whose linked Destiny account you want to return. 393 394 Other Parameters 395 ---------------- 396 all : `bool` 397 If provided and set to `True`, All memberships regardless 398 of whether they're obscured by overrides will be returned, 399 400 If provided and set to `False`, Only available memberships will be returned. 401 The default for this is `False`. 402 403 Returns 404 ------- 405 `aiobungie.crates.profile.LinkedProfile` 406 A linked profile object. 407 """ 408 resp = await self.rest.fetch_linked_profiles(member_id, member_type, all=all) 409 410 return self.factory.deserialize_linked_profiles(resp)
Returns a summary information about all profiles linked to the requested member.
The passed membership id/type maybe a Bungie.Net membership or a Destiny memberships.
It will only return linked accounts whose linkages you are allowed to view.
Parameters
- member_id (
int): The ID of the membership. This must be a valid Bungie.Net or PSN or Xbox ID. - member_type (
aiobungie.MembershipType): The type for the membership whose linked Destiny account you want to return.
Other Parameters
all (
bool): If provided and set toTrue, All memberships regardless of whether they're obscured by overrides will be returned,If provided and set to
False, Only available memberships will be returned. The default for this isFalse.
Returns
aiobungie.crates.profile.LinkedProfile: A linked profile object.
412 async def fetch_player( 413 self, 414 name: str, 415 code: int, 416 /, 417 type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.ALL, 418 ) -> collections.Sequence[user.DestinyMembership]: 419 """Fetch a Destiny 2 player's memberships. 420 421 Parameters 422 ----------- 423 name: `str` 424 The unique Bungie player name. 425 code : `int` 426 The unique Bungie display name code. 427 type: `aiobungie.internal.enums.MembershipType` 428 The player's membership type, e,g. XBOX, STEAM, PSN 429 430 Returns 431 -------- 432 `collections.Sequence[aiobungie.crates.DestinyMembership]` 433 A sequence of the found Destiny 2 player memberships. 434 An empty sequence will be returned if no one found. 435 436 Raises 437 ------ 438 `aiobungie.MembershipTypeError` 439 The provided membership type was invalid. 440 """ 441 resp = await self.rest.fetch_player(name, code, type) 442 443 return self.factory.deserialize_destiny_memberships(resp)
Fetch a Destiny 2 player's memberships.
Parameters
- name (
str): The unique Bungie player name. - code (
int): The unique Bungie display name code. - type (
MembershipType): The player's membership type, e,g. XBOX, STEAM, PSN
Returns
collections.Sequence[aiobungie.crates.DestinyMembership]: A sequence of the found Destiny 2 player memberships. An empty sequence will be returned if no one found.
Raises
aiobungie.MembershipTypeError: The provided membership type was invalid.
445 async def fetch_character( 446 self, 447 member_id: int, 448 membership_type: typedefs.IntAnd[enums.MembershipType], 449 character_id: int, 450 components: list[enums.ComponentType], 451 auth: typing.Optional[str] = None, 452 ) -> components.CharacterComponent: 453 """Fetch a Destiny 2 character. 454 455 Parameters 456 ---------- 457 member_id: `int` 458 A valid bungie member id. 459 character_id: `int` 460 The Destiny character id to retrieve. 461 membership_type: `aiobungie.internal.enums.MembershipType` 462 The member's membership type. 463 components: `list[aiobungie.ComponentType]` 464 Multiple arguments of character components to collect and return. 465 466 Other Parameters 467 ---------------- 468 auth : `typing.Optional[str]` 469 A Bearer access_token to make the request with. 470 This is optional and limited to components that only requires an Authorization token. 471 472 Returns 473 ------- 474 `aiobungie.crates.CharacterComponent` 475 A Bungie character component. 476 477 `aiobungie.MembershipTypeError` 478 The provided membership type was invalid. 479 """ 480 resp = await self.rest.fetch_character( 481 member_id, membership_type, character_id, components, auth 482 ) 483 484 return self.factory.deserialize_character_component(resp)
Fetch a Destiny 2 character.
Parameters
- member_id (
int): A valid bungie member id. - character_id (
int): The Destiny character id to retrieve. - membership_type (
MembershipType): The member's membership type. - components (
list[aiobungie.ComponentType]): Multiple arguments of character components to collect and return.
Other Parameters
- auth (
typing.Optional[str]): A Bearer access_token to make the request with. This is optional and limited to components that only requires an Authorization token.
Returns
aiobungie.crates.CharacterComponent: A Bungie character component.aiobungie.MembershipTypeError: The provided membership type was invalid.
486 async def fetch_unique_weapon_history( 487 self, 488 membership_id: int, 489 character_id: int, 490 membership_type: typedefs.IntAnd[enums.MembershipType], 491 ) -> collections.Sequence[activity.ExtendedWeaponValues]: 492 """Fetch details about unique weapon usage for a character. Includes all exotics. 493 494 Parameters 495 ---------- 496 membership_id : `int` 497 The Destiny user membership id. 498 character_id : `int` 499 The character id to retrieve. 500 membership_type : `aiobungie.typedefs.IntAnd[aiobungie.MembershipType]` 501 The Destiny user's membership type. 502 503 Returns 504 ------- 505 `collections.Sequence[aiobungie.crates.ExtendedWeaponValues]` 506 A sequence of the weapon's extended values. 507 """ 508 resp = await self._rest.fetch_unique_weapon_history( 509 membership_id, character_id, membership_type 510 ) 511 512 return [ 513 self._factory.deserialize_extended_weapon_values(weapon) 514 for weapon in resp["weapons"] 515 ]
Fetch details about unique weapon usage for a character. Includes all exotics.
Parameters
- membership_id (
int): The Destiny user membership id. - character_id (
int): The character id to retrieve. - membership_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The Destiny user's membership type.
Returns
collections.Sequence[aiobungie.crates.ExtendedWeaponValues]: A sequence of the weapon's extended values.
519 async def fetch_activities( 520 self, 521 member_id: int, 522 character_id: int, 523 mode: typedefs.IntAnd[enums.GameMode], 524 *, 525 membership_type: typedefs.IntAnd[ 526 enums.MembershipType 527 ] = enums.MembershipType.ALL, 528 page: int = 0, 529 limit: int = 250, 530 ) -> iterators.Iterator[activity.Activity]: 531 """Fetch a Destiny 2 activity for the specified character id. 532 533 Parameters 534 ---------- 535 member_id: `int` 536 The user id that starts with `4611`. 537 character_id: `int` 538 The id of the character to retrieve the activities for. 539 mode: `aiobungie.typedefs.IntAnd[aiobungie.internal.enums.GameMode]` 540 This parameter filters the game mode, Nightfall, Strike, Iron Banner, etc. 541 542 Other Parameters 543 ---------------- 544 membership_type: `aiobungie.internal.enums.MembershipType` 545 The Member ship type, if nothing was passed than it will return all. 546 page: int 547 The page number. Default is `0` 548 limit: int 549 Limit the returned result. Default is `250`. 550 551 Returns 552 ------- 553 `aiobungie.iterators.Iterator[aiobungie.crates.Activity]` 554 An iterator of the player's activities. 555 556 Raises 557 ------ 558 `aiobungie.MembershipTypeError` 559 The provided membership type was invalid. 560 """ 561 resp = await self.rest.fetch_activities( 562 member_id, 563 character_id, 564 mode, 565 membership_type=membership_type, 566 page=page, 567 limit=limit, 568 ) 569 570 return self.factory.deserialize_activities(resp)
Fetch a Destiny 2 activity for the specified character id.
Parameters
- member_id (
int): The user id that starts with4611. - character_id (
int): The id of the character to retrieve the activities for. - mode (
aiobungie.typedefs.IntAnd[GameMode]): This parameter filters the game mode, Nightfall, Strike, Iron Banner, etc.
Other Parameters
- membership_type (
MembershipType): The Member ship type, if nothing was passed than it will return all. - page (int):
The page number. Default is
0 - limit (int):
Limit the returned result. Default is
250.
Returns
aiobungie.iterators.Iterator[aiobungie.crates.Activity]: An iterator of the player's activities.
Raises
aiobungie.MembershipTypeError: The provided membership type was invalid.
572 async def fetch_post_activity(self, instance_id: int, /) -> activity.PostActivity: 573 """Fetch a post activity details. 574 575 Parameters 576 ---------- 577 instance_id: `int` 578 The activity instance id. 579 580 Returns 581 ------- 582 `aiobungie.crates.PostActivity` 583 A post activity object. 584 """ 585 resp = await self.rest.fetch_post_activity(instance_id) 586 587 return self.factory.deserialize_post_activity(resp)
Fetch a post activity details.
Parameters
- instance_id (
int): The activity instance id.
Returns
aiobungie.crates.PostActivity: A post activity object.
589 async def fetch_aggregated_activity_stats( 590 self, 591 character_id: int, 592 membership_id: int, 593 membership_type: typedefs.IntAnd[enums.MembershipType], 594 ) -> iterators.Iterator[activity.AggregatedActivity]: 595 """Fetch aggregated activity stats for a character. 596 597 Parameters 598 ---------- 599 character_id: `int` 600 The id of the character to retrieve the activities for. 601 membership_id: `int` 602 The id of the user that started with `4611`. 603 membership_type: `aiobungie.internal.enums.MembershipType` 604 The Member ship type. 605 606 Returns 607 ------- 608 `aiobungie.iterators.Iterator[aiobungie.crates.AggregatedActivity]` 609 An iterator of the player's activities. 610 611 Raises 612 ------ 613 `aiobungie.MembershipTypeError` 614 The provided membership type was invalid. 615 """ 616 resp = await self.rest.fetch_aggregated_activity_stats( 617 character_id, membership_id, membership_type 618 ) 619 620 return self.factory.deserialize_aggregated_activities(resp)
Fetch aggregated activity stats for a character.
Parameters
- character_id (
int): The id of the character to retrieve the activities for. - membership_id (
int): The id of the user that started with4611. - membership_type (
MembershipType): The Member ship type.
Returns
aiobungie.iterators.Iterator[aiobungie.crates.AggregatedActivity]: An iterator of the player's activities.
Raises
aiobungie.MembershipTypeError: The provided membership type was invalid.
624 async def fetch_clan_from_id( 625 self, 626 id: int, 627 /, 628 access_token: typing.Optional[str] = None, 629 ) -> clans.Clan: 630 """Fetch a Bungie Clan by its id. 631 632 Parameters 633 ----------- 634 id: `int` 635 The clan id. 636 637 Returns 638 -------- 639 `aiobungie.crates.Clan` 640 An Bungie clan. 641 642 Raises 643 ------ 644 `aiobungie.NotFound` 645 The clan was not found. 646 """ 647 resp = await self.rest.fetch_clan_from_id(id, access_token) 648 649 return self.factory.deserialize_clan(resp)
Fetch a Bungie Clan by its id.
Parameters
- id (
int): The clan id.
Returns
aiobungie.crates.Clan: An Bungie clan.
Raises
aiobungie.NotFound: The clan was not found.
651 async def fetch_clan( 652 self, 653 name: str, 654 /, 655 access_token: typing.Optional[str] = None, 656 *, 657 type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN, 658 ) -> clans.Clan: 659 """Fetch a Clan by its name. 660 This method will return the first clan found with given name. 661 662 Parameters 663 ---------- 664 name: `str` 665 The clan name 666 667 Other Parameters 668 ---------------- 669 access_token : `typing.Optional[str]` 670 An optional access token to make the request with. 671 672 If the token was bound to a member of the clan, 673 This field `aiobungie.crates.Clan.current_user_membership` will be available 674 and will return the membership of the user who made this request. 675 type : `aiobungie.GroupType` 676 The group type, Default is aiobungie.GroupType.CLAN. 677 678 Returns 679 ------- 680 `aiobungie.crates.Clan` 681 A Bungie clan. 682 683 Raises 684 ------ 685 `aiobungie.NotFound` 686 The clan was not found. 687 """ 688 resp = await self.rest.fetch_clan(name, access_token, type=type) 689 690 return self.factory.deserialize_clan(resp)
Fetch a Clan by its name. This method will return the first clan found with given name.
Parameters
- name (
str): The clan name
Other Parameters
access_token (
typing.Optional[str]): An optional access token to make the request with.If the token was bound to a member of the clan, This field
aiobungie.crates.Clan.current_user_membershipwill be available and will return the membership of the user who made this request.- type (
aiobungie.GroupType): The group type, Default is aiobungie.GroupType.CLAN.
Returns
aiobungie.crates.Clan: A Bungie clan.
Raises
aiobungie.NotFound: The clan was not found.
692 async def fetch_clan_conversations( 693 self, clan_id: int, / 694 ) -> collections.Sequence[clans.ClanConversation]: 695 """Fetch the conversations/chat channels of the given clan id. 696 697 Parameters 698 ---------- 699 clan_id : `int` 700 The clan id. 701 702 Returns 703 `collections.Sequence[aiobungie.crates.ClanConversation]` 704 A sequence of the clan chat channels. 705 """ 706 resp = await self.rest.fetch_clan_conversations(clan_id) 707 708 return self.factory.deserialize_clan_conversations(resp)
Fetch the conversations/chat channels of the given clan id.
Parameters
- clan_id (
int): The clan id. - Returns
collections.Sequence[aiobungie.crates.ClanConversation]: A sequence of the clan chat channels.
710 async def fetch_clan_admins( 711 self, clan_id: int, / 712 ) -> iterators.Iterator[clans.ClanMember]: 713 """Fetch the clan founder and admins. 714 715 Parameters 716 ---------- 717 clan_id : `int` 718 The clan id. 719 720 Returns 721 ------- 722 `aiobungie.iterators.Iterator[aiobungie.crates.ClanMember]` 723 An iterator over the found clan admins and founder. 724 725 Raises 726 ------ 727 `aiobungie.NotFound` 728 The requested clan was not found. 729 """ 730 resp = await self.rest.fetch_clan_admins(clan_id) 731 732 return self.factory.deserialize_clan_members(resp)
Fetch the clan founder and admins.
Parameters
- clan_id (
int): The clan id.
Returns
aiobungie.iterators.Iterator[aiobungie.crates.ClanMember]: An iterator over the found clan admins and founder.
Raises
aiobungie.NotFound: The requested clan was not found.
734 async def fetch_groups_for_member( 735 self, 736 member_id: int, 737 member_type: typedefs.IntAnd[enums.MembershipType], 738 /, 739 *, 740 filter: int = 0, 741 group_type: enums.GroupType = enums.GroupType.CLAN, 742 ) -> collections.Sequence[clans.GroupMember]: 743 """Fetch information about the groups that a given member has joined. 744 745 Parameters 746 ---------- 747 member_id : `int` 748 The member's id 749 member_type : `aiobungie.MembershipType` 750 The member's membership type. 751 752 Other Parameters 753 ---------------- 754 filter : `int` 755 Filter apply to list of joined groups. This Default to `0` 756 group_type : `aiobungie.GroupType` 757 The group's type. 758 This is always set to `aiobungie.GroupType.CLAN` and should not be changed. 759 760 Returns 761 ------- 762 `collections.Sequence[aiobungie.crates.GroupMember]` 763 A sequence of joined groups for the fetched member. 764 """ 765 resp = await self.rest.fetch_groups_for_member( 766 member_id, member_type, filter=filter, group_type=group_type 767 ) 768 769 return [ 770 self.factory.deserialize_group_member(group) for group in resp["results"] 771 ]
Fetch information about the groups that a given member has joined.
Parameters
- member_id (
int): The member's id - member_type (
aiobungie.MembershipType): The member's membership type.
Other Parameters
- filter (
int): Filter apply to list of joined groups. This Default to0 - group_type (
aiobungie.GroupType): The group's type. This is always set toaiobungie.GroupType.CLANand should not be changed.
Returns
collections.Sequence[aiobungie.crates.GroupMember]: A sequence of joined groups for the fetched member.
773 async def fetch_potential_groups_for_member( 774 self, 775 member_id: int, 776 member_type: typedefs.IntAnd[enums.MembershipType], 777 /, 778 *, 779 filter: int = 0, 780 group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN, 781 ) -> collections.Sequence[clans.GroupMember]: 782 """Fetch the potential groups for a clan member. 783 784 Parameters 785 ---------- 786 member_id : `int` 787 The member's id 788 member_type : `aiobungie.typedefs.IntAnd[aiobungie.MembershipType]` 789 The member's membership type. 790 791 Other Parameters 792 ---------------- 793 filter : `int` 794 Filter apply to list of joined groups. This Default to `0` 795 group_type : `aiobungie.typedefs.IntAnd[aiobungie.GroupType]` 796 The group's type. 797 This is always set to `aiobungie.GroupType.CLAN` and should not be changed. 798 799 Returns 800 ------- 801 `collections.Sequence[aiobungie.crates.GroupMember]` 802 A sequence of joined potential groups for the fetched member. 803 """ 804 resp = await self.rest.fetch_potential_groups_for_member( 805 member_id, member_type, filter=filter, group_type=group_type 806 ) 807 808 return [ 809 self.factory.deserialize_group_member(group) for group in resp["results"] 810 ]
Fetch the potential groups for a clan member.
Parameters
- member_id (
int): The member's id - member_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The member's membership type.
Other Parameters
- filter (
int): Filter apply to list of joined groups. This Default to0 - group_type (
aiobungie.typedefs.IntAnd[aiobungie.GroupType]): The group's type. This is always set toaiobungie.GroupType.CLANand should not be changed.
Returns
collections.Sequence[aiobungie.crates.GroupMember]: A sequence of joined potential groups for the fetched member.
812 async def fetch_clan_members( 813 self, 814 clan_id: int, 815 /, 816 *, 817 name: typing.Optional[str] = None, 818 type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE, 819 ) -> iterators.Iterator[clans.ClanMember]: 820 """Fetch Bungie clan members. 821 822 Parameters 823 ---------- 824 clan_id : `int` 825 The clans id 826 827 Other Parameters 828 ---------------- 829 name : `typing.Optional[str]` 830 If provided, Only players matching this name will be returned. 831 type : `aiobungie.MembershipType` 832 An optional clan member's membership type. 833 This parameter is used to filter the returned results 834 by the provided membership, For an example XBox memberships only, 835 Otherwise will return all memberships. 836 837 Returns 838 ------- 839 `aiobungie.iterators.Iterator[aiobungie.crates.ClanMember]` 840 An iterator over the bungie clan members. 841 842 Raises 843 ------ 844 `aiobungie.NotFound` 845 The clan was not found. 846 """ 847 resp = await self.rest.fetch_clan_members(clan_id, type=type, name=name) 848 849 return self.factory.deserialize_clan_members(resp)
Fetch Bungie clan members.
Parameters
- clan_id (
int): The clans id
Other Parameters
- name (
typing.Optional[str]): If provided, Only players matching this name will be returned. - type (
aiobungie.MembershipType): An optional clan member's membership type. This parameter is used to filter the returned results by the provided membership, For an example XBox memberships only, Otherwise will return all memberships.
Returns
aiobungie.iterators.Iterator[aiobungie.crates.ClanMember]: An iterator over the bungie clan members.
Raises
aiobungie.NotFound: The clan was not found.
864 async def kick_clan_member( 865 self, 866 access_token: str, 867 /, 868 group_id: int, 869 membership_id: int, 870 membership_type: typedefs.IntAnd[enums.MembershipType], 871 ) -> clans.Clan: 872 """Kick a member from the clan. 873 874 .. note:: 875 This request requires OAuth2: oauth2: `AdminGroups` scope. 876 877 Parameters 878 ---------- 879 access_token : `str` 880 The bearer access token associated with the bungie account. 881 group_id: `int` 882 The group id. 883 membership_id : `int` 884 The member id to kick. 885 membership_type : `aiobungie.typedefs.IntAnd[aiobungie.MembershipType]` 886 The member's membership type. 887 888 Returns 889 ------- 890 `aiobungie.crates.clan.Clan` 891 The clan that the member was kicked from. 892 """ 893 resp = await self.rest.kick_clan_member( 894 access_token, 895 group_id=group_id, 896 membership_id=membership_id, 897 membership_type=membership_type, 898 ) 899 900 return self.factory.deserialize_clan(resp)
Kick a member from the clan.
This request requires OAuth2: oauth2: AdminGroups scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - group_id (
int): The group id. - membership_id (
int): The member id to kick. - membership_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The member's membership type.
Returns
aiobungie.crates.clan.Clan: The clan that the member was kicked from.
902 async def fetch_clan_weekly_rewards(self, clan_id: int) -> milestones.Milestone: 903 """Fetch a Bungie clan's weekly reward state. 904 905 Parameters 906 ---------- 907 clan_id : `int` 908 The clan's id. 909 910 Returns 911 ------- 912 `aiobungie.crates.Milestone` 913 A runtime status of the clan's milestone data. 914 """ 915 916 resp = await self.rest.fetch_clan_weekly_rewards(clan_id) 917 918 return self.factory.deserialize_milestone(resp)
Fetch a Bungie clan's weekly reward state.
Parameters
- clan_id (
int): The clan's id.
Returns
aiobungie.crates.Milestone: A runtime status of the clan's milestone data.
922 async def fetch_inventory_item(self, hash: int, /) -> entity.InventoryEntity: 923 """Fetch a static inventory item entity given a its hash. 924 925 Parameters 926 ---------- 927 hash: `int` 928 Inventory item's hash. 929 930 Returns 931 ------- 932 `aiobungie.crates.InventoryEntity` 933 A bungie inventory item. 934 """ 935 resp = await self.rest.fetch_inventory_item(hash) 936 937 return self.factory.deserialize_inventory_entity(resp)
Fetch a static inventory item entity given a its hash.
Parameters
- hash (
int): Inventory item's hash.
Returns
aiobungie.crates.InventoryEntity: A bungie inventory item.
939 async def fetch_objective_entity(self, hash: int, /) -> entity.ObjectiveEntity: 940 """Fetch a Destiny objective entity given a its hash. 941 942 Parameters 943 ---------- 944 hash: `int` 945 objective's hash. 946 947 Returns 948 ------- 949 `aiobungie.crates.ObjectiveEntity` 950 An objective entity item. 951 """ 952 resp = await self.rest.fetch_objective_entity(hash) 953 954 return self.factory.deserialize_objective_entity(resp)
Fetch a Destiny objective entity given a its hash.
Parameters
- hash (
int): objective's hash.
Returns
aiobungie.crates.ObjectiveEntity: An objective entity item.
956 async def search_entities( 957 self, name: str, entity_type: str, *, page: int = 0 958 ) -> iterators.Iterator[entity.SearchableEntity]: 959 """Search for Destiny2 entities given a name and its type. 960 961 Parameters 962 ---------- 963 name : `str` 964 The name of the entity, i.e., Thunderlord, One thousand voices. 965 entity_type : `str` 966 The type of the entity, AKA Definition, 967 For an example `DestinyInventoryItemDefinition` for emblems, weapons, and other inventory items. 968 969 Other Parameters 970 ---------------- 971 page : `int` 972 An optional page to return. Default to 0. 973 974 Returns 975 ------- 976 `aiobungie.iterators.Iterator[aiobungie.crates.SearchableEntity]` 977 An iterator over the found results matching the provided name. 978 """ 979 resp = await self.rest.search_entities(name, entity_type, page=page) 980 981 return self.factory.deserialize_inventory_results(resp)
Search for Destiny2 entities given a name and its type.
Parameters
- name (
str): The name of the entity, i.e., Thunderlord, One thousand voices. - entity_type (
str): The type of the entity, AKA Definition, For an exampleDestinyInventoryItemDefinitionfor emblems, weapons, and other inventory items.
Other Parameters
- page (
int): An optional page to return. Default to 0.
Returns
aiobungie.iterators.Iterator[aiobungie.crates.SearchableEntity]: An iterator over the found results matching the provided name.
985 async def fetch_fireteams( 986 self, 987 activity_type: typedefs.IntAnd[fireteams.FireteamActivity], 988 *, 989 platform: typedefs.IntAnd[ 990 fireteams.FireteamPlatform 991 ] = fireteams.FireteamPlatform.ANY, 992 language: typing.Union[ 993 fireteams.FireteamLanguage, str 994 ] = fireteams.FireteamLanguage.ALL, 995 date_range: int = 0, 996 page: int = 0, 997 slots_filter: int = 0, 998 ) -> typing.Optional[collections.Sequence[fireteams.Fireteam]]: 999 """Fetch public Bungie fireteams with open slots. 1000 1001 Parameters 1002 ---------- 1003 activity_type : `aiobungie.typedefs.IntAnd[aiobungie.crates.FireteamActivity]` 1004 The fireteam activity type. 1005 1006 Other Parameters 1007 ---------------- 1008 platform : `aiobungie.typedefs.IntAnd[aiobungie.crates.fireteams.FireteamPlatform]` 1009 If this is provided. Then the results will be filtered with the given platform. 1010 Defaults to `aiobungie.crates.FireteamPlatform.ANY` which returns all platforms. 1011 language : `typing.Union[aiobungie.crates.fireteams.FireteamLanguage, str]` 1012 A locale language to filter the used language in that fireteam. 1013 Defaults to `aiobungie.crates.FireteamLanguage.ALL` 1014 date_range : `int` 1015 An integer to filter the date range of the returned fireteams. Defaults to `aiobungie.FireteamDate.ALL`. 1016 page : `int` 1017 The page number. By default its `0` which returns all available activities. 1018 slots_filter : `int` 1019 Filter the returned fireteams based on available slots. Default is `0` 1020 1021 Returns 1022 ------- 1023 `typing.Optional[collections.Sequence[fireteams.Fireteam]]` 1024 A sequence of `aiobungie.crates.Fireteam` or `None`. 1025 """ 1026 1027 resp = await self.rest.fetch_fireteams( 1028 activity_type, 1029 platform=platform, 1030 language=language, 1031 date_range=date_range, 1032 page=page, 1033 slots_filter=slots_filter, 1034 ) 1035 1036 return self.factory.deserialize_fireteams(resp)
Fetch public Bungie fireteams with open slots.
Parameters
- activity_type (
aiobungie.typedefs.IntAnd[aiobungie.crates.FireteamActivity]): The fireteam activity type.
Other Parameters
- platform (
aiobungie.typedefs.IntAnd[FireteamPlatform]): If this is provided. Then the results will be filtered with the given platform. Defaults toaiobungie.crates.FireteamPlatform.ANYwhich returns all platforms. - language (
typing.Union[FireteamLanguage, str]): A locale language to filter the used language in that fireteam. Defaults toaiobungie.crates.FireteamLanguage.ALL - date_range (
int): An integer to filter the date range of the returned fireteams. Defaults toaiobungie.FireteamDate.ALL. - page (
int): The page number. By default its0which returns all available activities. - slots_filter (
int): Filter the returned fireteams based on available slots. Default is0
Returns
typing.Optional[collections.Sequence[fireteams.Fireteam]]: A sequence ofaiobungie.crates.FireteamorNone.
1038 async def fetch_avaliable_clan_fireteams( 1039 self, 1040 access_token: str, 1041 group_id: int, 1042 activity_type: typedefs.IntAnd[fireteams.FireteamActivity], 1043 *, 1044 platform: typedefs.IntAnd[fireteams.FireteamPlatform], 1045 language: typing.Union[fireteams.FireteamLanguage, str], 1046 date_range: int = 0, 1047 page: int = 0, 1048 public_only: bool = False, 1049 slots_filter: int = 0, 1050 ) -> typing.Optional[collections.Sequence[fireteams.Fireteam]]: 1051 """Fetch a clan's fireteams with open slots. 1052 1053 .. note:: 1054 This method requires OAuth2: ReadGroups scope. 1055 1056 Parameters 1057 ---------- 1058 access_token : `str` 1059 The bearer access token associated with the bungie account. 1060 group_id : `int` 1061 The group/clan id of the fireteam. 1062 activity_type : `aiobungie.typedefs.IntAnd[aiobungie.crates.FireteamActivity]` 1063 The fireteam activity type. 1064 1065 Other Parameters 1066 ---------------- 1067 platform : `aiobungie.typedefs.IntAnd[aiobungie.crates.fireteams.FireteamPlatform]` 1068 If this is provided. Then the results will be filtered with the given platform. 1069 Defaults to `aiobungie.crates.FireteamPlatform.ANY` which returns all platforms. 1070 language : `typing.Union[aiobungie.crates.fireteams.FireteamLanguage, str]` 1071 A locale language to filter the used language in that fireteam. 1072 Defaults to `aiobungie.crates.FireteamLanguage.ALL` 1073 date_range : `int` 1074 An integer to filter the date range of the returned fireteams. Defaults to `0`. 1075 page : `int` 1076 The page number. By default its `0` which returns all available activities. 1077 public_only: `bool` 1078 If set to True, Then only public fireteams will be returned. 1079 slots_filter : `int` 1080 Filter the returned fireteams based on available slots. Default is `0` 1081 1082 Returns 1083 ------- 1084 `typing.Optional[collections.Sequence[aiobungie.crates.Fireteam]]` 1085 A sequence of fireteams found in the clan. 1086 `None` will be returned if nothing was found. 1087 """ 1088 resp = await self.rest.fetch_avaliable_clan_fireteams( 1089 access_token, 1090 group_id, 1091 activity_type, 1092 platform=platform, 1093 language=language, 1094 date_range=date_range, 1095 page=page, 1096 public_only=public_only, 1097 slots_filter=slots_filter, 1098 ) 1099 1100 return self.factory.deserialize_fireteams(resp)
Fetch a clan's fireteams with open slots.
This method requires OAuth2: ReadGroups scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - group_id (
int): The group/clan id of the fireteam. - activity_type (
aiobungie.typedefs.IntAnd[aiobungie.crates.FireteamActivity]): The fireteam activity type.
Other Parameters
- platform (
aiobungie.typedefs.IntAnd[FireteamPlatform]): If this is provided. Then the results will be filtered with the given platform. Defaults toaiobungie.crates.FireteamPlatform.ANYwhich returns all platforms. - language (
typing.Union[FireteamLanguage, str]): A locale language to filter the used language in that fireteam. Defaults toaiobungie.crates.FireteamLanguage.ALL - date_range (
int): An integer to filter the date range of the returned fireteams. Defaults to0. - page (
int): The page number. By default its0which returns all available activities. - public_only (
bool): If set to True, Then only public fireteams will be returned. - slots_filter (
int): Filter the returned fireteams based on available slots. Default is0
Returns
typing.Optional[collections.Sequence[aiobungie.crates.Fireteam]]: A sequence of fireteams found in the clan.Nonewill be returned if nothing was found.
1102 async def fetch_clan_fireteam( 1103 self, access_token: str, fireteam_id: int, group_id: int 1104 ) -> fireteams.AvailableFireteam: 1105 """Fetch a specific clan fireteam. 1106 1107 .. note:: 1108 This method requires OAuth2: ReadGroups scope. 1109 1110 Parameters 1111 ---------- 1112 access_token : `str` 1113 The bearer access token associated with the bungie account. 1114 group_id : `int` 1115 The group/clan id to fetch the fireteam from. 1116 fireteam_id : `int` 1117 The fireteam id to fetch. 1118 1119 Returns 1120 ------- 1121 `typing.Optional[aiobungie.crates.AvailableFireteam]` 1122 A sequence of available fireteams objects if exists. else `None` will be returned. 1123 """ 1124 resp = await self.rest.fetch_clan_fireteam(access_token, fireteam_id, group_id) 1125 1126 return self.factory.deserialize_available_fireteams( 1127 resp, no_results=True 1128 ) # type: ignore[return-value]
Fetch a specific clan fireteam.
This method requires OAuth2: ReadGroups scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - group_id (
int): The group/clan id to fetch the fireteam from. - fireteam_id (
int): The fireteam id to fetch.
Returns
typing.Optional[aiobungie.crates.AvailableFireteam]: A sequence of available fireteams objects if exists. elseNonewill be returned.
1130 async def fetch_my_clan_fireteams( 1131 self, 1132 access_token: str, 1133 group_id: int, 1134 *, 1135 include_closed: bool = True, 1136 platform: typedefs.IntAnd[fireteams.FireteamPlatform], 1137 language: typing.Union[fireteams.FireteamLanguage, str], 1138 filtered: bool = True, 1139 page: int = 0, 1140 ) -> collections.Sequence[fireteams.AvailableFireteam]: 1141 """A method that's similar to `fetch_fireteams` but requires OAuth2. 1142 1143 .. note:: 1144 This method requires OAuth2: ReadGroups scope. 1145 1146 Parameters 1147 ---------- 1148 access_token : str 1149 The bearer access token associated with the bungie account. 1150 group_id : int 1151 The group/clan id to fetch. 1152 1153 Other Parameters 1154 ---------------- 1155 include_closed : bool 1156 If provided and set to True, It will also return closed fireteams. 1157 If provided and set to False, It will only return public fireteams. Default is True. 1158 platform : aiobungie.typedefs.IntAnd[aiobungie.crates.fireteams.FireteamPlatform] 1159 If this is provided. Then the results will be filtered with the given platform. 1160 Defaults to aiobungie.crates.FireteamPlatform.ANY which returns all platforms. 1161 language : typing.Union[aiobungie.crates.fireteams.FireteamLanguage, str] 1162 A locale language to filter the used language in that fireteam. 1163 Defaults to aiobungie.crates.FireteamLanguage.ALL 1164 filtered : bool 1165 If set to True, it will filter by clan. Otherwise not. Default is True. 1166 page : int 1167 The page number. By default its 0 which returns all available activities. 1168 1169 Returns 1170 ------- 1171 `collections.Sequence[aiobungie.crates.AvailableFireteam]` 1172 A sequence of available fireteams objects if exists. else `None` will be returned. 1173 """ 1174 resp = await self.rest.fetch_my_clan_fireteams( 1175 access_token, 1176 group_id, 1177 include_closed=include_closed, 1178 platform=platform, 1179 language=language, 1180 filtered=filtered, 1181 page=page, 1182 ) 1183 1184 return self.factory.deserialize_available_fireteams(resp) # type: ignore[return-value]
A method that's similar to fetch_fireteams but requires OAuth2.
This method requires OAuth2: ReadGroups scope.
Parameters
- access_token (str): The bearer access token associated with the bungie account.
- group_id (int): The group/clan id to fetch.
Other Parameters
- include_closed (bool): If provided and set to True, It will also return closed fireteams. If provided and set to False, It will only return public fireteams. Default is True.
- platform (aiobungie.typedefs.IntAnd[FireteamPlatform]): If this is provided. Then the results will be filtered with the given platform. Defaults to aiobungie.crates.FireteamPlatform.ANY which returns all platforms.
- language (typing.Union[FireteamLanguage, str]): A locale language to filter the used language in that fireteam. Defaults to aiobungie.crates.FireteamLanguage.ALL
- filtered (bool): If set to True, it will filter by clan. Otherwise not. Default is True.
- page (int): The page number. By default its 0 which returns all available activities.
Returns
collections.Sequence[aiobungie.crates.AvailableFireteam]: A sequence of available fireteams objects if exists. elseNonewill be returned.
1188 async def fetch_friends( 1189 self, access_token: str, / 1190 ) -> collections.Sequence[friends.Friend]: 1191 """Fetch bungie friend list. 1192 1193 .. note:: 1194 This requests OAuth2: ReadUserData scope. 1195 1196 Parameters 1197 ----------- 1198 access_token : `str` 1199 The bearer access token associated with the bungie account. 1200 1201 Returns 1202 ------- 1203 `collections.Sequence[aiobungie.crates.Friend]` 1204 A sequence of the friends associated with that access token. 1205 """ 1206 1207 resp = await self.rest.fetch_friends(access_token) 1208 1209 return self.factory.deserialize_friends(resp)
Fetch bungie friend list.
This requests OAuth2: ReadUserData scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account.
Returns
collections.Sequence[aiobungie.crates.Friend]: A sequence of the friends associated with that access token.
1211 async def fetch_friend_requests( 1212 self, access_token: str, / 1213 ) -> friends.FriendRequestView: 1214 """Fetch pending bungie friend requests queue. 1215 1216 .. note:: 1217 This requests OAuth2: ReadUserData scope. 1218 1219 Parameters 1220 ----------- 1221 access_token : `str` 1222 The bearer access token associated with the bungie account. 1223 1224 Returns 1225 ------- 1226 `aiobungie.crates.FriendRequestView` 1227 A friend requests view of that associated access token. 1228 """ 1229 1230 resp = await self.rest.fetch_friend_requests(access_token) 1231 1232 return self.factory.deserialize_friend_requests(resp)
Fetch pending bungie friend requests queue.
This requests OAuth2: ReadUserData scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account.
Returns
aiobungie.crates.FriendRequestView: A friend requests view of that associated access token.
1236 async def fetch_application(self, appid: int, /) -> application.Application: 1237 """Fetch a Bungie application. 1238 1239 Parameters 1240 ----------- 1241 appid: `int` 1242 The application id. 1243 1244 Returns 1245 -------- 1246 `aiobungie.crates.Application` 1247 A Bungie application. 1248 """ 1249 resp = await self.rest.fetch_application(appid) 1250 1251 return self.factory.deserialize_app(resp)
Fetch a Bungie application.
Parameters
- appid (
int): The application id.
Returns
aiobungie.crates.Application: A Bungie application.
1255 async def fetch_public_milestone_content( 1256 self, milestone_hash: int, / 1257 ) -> milestones.MilestoneContent: 1258 """Fetch the milestone content given its hash. 1259 1260 Parameters 1261 ---------- 1262 milestone_hash : `int` 1263 The milestone hash. 1264 1265 Returns 1266 ------- 1267 `aiobungie.crates.milestones.MilestoneContent` 1268 A milestone content object. 1269 """ 1270 resp = await self.rest.fetch_public_milestone_content(milestone_hash) 1271 1272 return self.factory.deserialize_public_milestone_content(resp)
Fetch the milestone content given its hash.
Parameters
- milestone_hash (
int): The milestone hash.
Returns
aiobungie.crates.milestones.MilestoneContent: A milestone content object.
771@typing.final 772class ClosedReasons(Flag): 773 """A Flags enumeration representing the reasons why a person can't join this user's fireteam.""" 774 775 NONE = 0 776 MATCHMAKING = 1 << 0 777 LOADING = 1 << 1 778 SOLO = 1 << 2 779 """The activity is required to be played solo.""" 780 INTERNAL_REASONS = 1 << 3 781 """ 782 The user can't be joined for one of a variety of internal reasons. 783 Basically, the game can't let you join at this time, 784 but for reasons that aren't under the control of this user 785 """ 786 DISALLOWED_BY_GAME_STATE = 1 << 4 787 """The user's current activity/quest/other transitory game state is preventing joining.""" 788 OFFLINE = 32768 789 """The user appears offline."""
A Flags enumeration representing the reasons why a person can't join this user's fireteam.
The user can't be joined for one of a variety of internal reasons. Basically, the game can't let you join at this time, but for reasons that aren't under the control of this user
The user's current activity/quest/other transitory game state is preventing joining.
74@typing.final 75class ComponentFields(enums.Enum): 76 """An enum that provides fields found in a base component response.""" 77 78 PRIVACY = ComponentPrivacy 79 DISABLED = False
An enum that provides fields found in a base component response.
65@typing.final 66class ComponentPrivacy(int, enums.Enum): 67 """An enum the provides privacy settings for profile components.""" 68 69 NONE = 0 70 PUBLIC = 1 71 PRIVATE = 2
An enum the provides privacy settings for profile components.
348@typing.final 349class ComponentType(Enum): 350 """An Enum for Destiny 2 profile Components.""" 351 352 NONE = 0 353 354 PROFILE = 100 355 PROFILE_INVENTORIES = 102 356 PROFILE_CURRENCIES = 103 357 PROFILE_PROGRESSION = 104 358 ALL_PROFILES = ( 359 PROFILE, 360 PROFILE_INVENTORIES, 361 PROFILE_CURRENCIES, 362 PROFILE_PROGRESSION, 363 ) 364 """All profile components.""" 365 366 VENDORS = 400 367 VENDOR_SALES = 402 368 VENDOR_RECEIPTS = 101 369 ALL_VENDORS = (VENDORS, VENDOR_RECEIPTS, VENDOR_SALES) 370 """All vendor components.""" 371 372 # Items 373 ITEM_INSTANCES = 300 374 ITEM_OBJECTIVES = 301 375 ITEM_PERKS = 302 376 ITEM_RENDER_DATA = 303 377 ITEM_STATS = 304 378 ITEM_SOCKETS = 305 379 ITEM_TALENT_GRINDS = 306 380 ITEM_PLUG_STATES = 308 381 ITEM_PLUG_OBJECTIVES = 309 382 ITEM_REUSABLE_PLUGS = 310 383 384 ALL_ITEMS = ( 385 ITEM_PLUG_OBJECTIVES, 386 ITEM_PLUG_STATES, 387 ITEM_SOCKETS, 388 ITEM_INSTANCES, 389 ITEM_OBJECTIVES, 390 ITEM_PERKS, 391 ITEM_RENDER_DATA, 392 ITEM_STATS, 393 ITEM_TALENT_GRINDS, 394 ITEM_REUSABLE_PLUGS, 395 ) 396 """All item components.""" 397 398 PLATFORM_SILVER = 105 399 KIOSKS = 500 400 CURRENCY_LOOKUPS = 600 401 PRESENTATION_NODES = 700 402 COLLECTIBLES = 800 403 RECORDS = 900 404 TRANSITORY = 1000 405 METRICS = 1100 406 INVENTORIES = 102 407 STRING_VARIABLES = 1200 408 CRAFTABLES = 1300 409 410 CHARACTERS = 200 411 CHARACTER_INVENTORY = 201 412 CHARECTER_PROGRESSION = 202 413 CHARACTER_RENDER_DATA = 203 414 CHARACTER_ACTIVITIES = 204 415 CHARACTER_EQUIPMENT = 205 416 CHARACTER_LOADOUTS = 206 417 418 ALL_CHARACTERS = ( 419 CHARACTERS, 420 CHARACTER_INVENTORY, 421 CHARECTER_PROGRESSION, 422 CHARACTER_RENDER_DATA, 423 CHARACTER_ACTIVITIES, 424 CHARACTER_EQUIPMENT, 425 CHARACTER_LOADOUTS, 426 RECORDS, 427 ) 428 """All character components.""" 429 430 ALL = ( 431 *ALL_PROFILES, # type: ignore 432 *ALL_CHARACTERS, # type: ignore 433 *ALL_VENDORS, # type: ignore 434 *ALL_ITEMS, # type: ignore 435 RECORDS, 436 CURRENCY_LOOKUPS, 437 PRESENTATION_NODES, 438 COLLECTIBLES, 439 KIOSKS, 440 METRICS, 441 PLATFORM_SILVER, 442 INVENTORIES, 443 STRING_VARIABLES, 444 TRANSITORY, 445 CRAFTABLES, 446 ) 447 """ALl components included."""
An Enum for Destiny 2 profile Components.
All item components.
All character components.
ALl components included.
653@typing.final 654class CredentialType(int, Enum): 655 """The types of the accounts system supports at bungie.""" 656 657 NONE = 0 658 XUID = 1 659 PSNID = 2 660 WILD = 3 661 FAKE = 4 662 FACEBOOK = 5 663 GOOGLE = 8 664 WINDOWS = 9 665 DEMONID = 10 666 STEAMID = 12 667 BATTLENETID = 14 668 STADIAID = 16 669 TWITCHID = 18
The types of the accounts system supports at bungie.
531@typing.final 532class DamageType(int, Enum): 533 """Enums for Destiny Damage types""" 534 535 NONE = 0 536 KINETIC = 1 537 ARC = 2 538 SOLAR = 3 539 VOID = 4 540 RAID = 5 541 """This is a special damage type reserved for some raid activity encounters.""" 542 STASIS = 6
Enums for Destiny Damage types
This is a special damage type reserved for some raid activity encounters.
64@typing.final 65class Difficulty(int, enums.Enum): 66 """An enum for activities difficulties.""" 67 68 TRIVIAL = 0 69 EASY = 1 70 NORMAL = 2 71 CHALLENGING = 3 72 HARD = 4 73 BRAVE = 5 74 ALMOST_IMPOSSIBLE = 6 75 IMPOSSIBLE = 7
An enum for activities difficulties.
150@typing.final 151class Dungeon(int, Enum): 152 """An Enum for all available Dungeon/Like missions in Destiny 2.""" 153 154 NORMAL_PRESAGE = 2124066889 155 """Normal Presage""" 156 157 MASTER_PRESAGE = 4212753278 158 """Master Presage""" 159 160 HARBINGER = 1738383283 161 """Harbinger""" 162 163 PROPHECY = 4148187374 164 """Prophecy""" 165 166 MASTER_POH = 785700673 167 """Master Pit of Heresy?""" 168 169 LEGEND_POH = 785700678 170 """Legend Pit of Heresy?""" 171 172 POH = 1375089621 173 """Normal Pit of Heresy.""" 174 175 SHATTERED = 2032534090 176 """Shattered Throne""" 177 178 GOA_LEGEND = 4078656646 179 """Grasp of Avarice legend.""" 180 181 GOA_MASTER = 3774021532 182 """Grasp of Avarice master."""
An Enum for all available Dungeon/Like missions in Destiny 2.
70class Enum(__enum.Enum): 71 """Builtin Python enum with extra handlings.""" 72 73 @property 74 def name(self) -> str: # type: ignore[override] 75 return self._name_ 76 77 @property 78 def value(self) -> typing.Any: # type: ignore[override] 79 return self._value_ 80 81 def __str__(self) -> str: 82 return self._name_ 83 84 def __repr__(self) -> str: 85 return f"<{type(self).__name__}.{self._name_}: {self._value_!s}>" 86 87 def __int__(self) -> int: 88 return int(self.value)
Builtin Python enum with extra handlings.
61class Factory(interfaces.FactoryInterface): 62 """The base deserialization factory class for all aiobungie objects. 63 64 This entity factory is used to deserialize JSON responses from the REST client and turning them 65 into a `aiobungie.crates` Python classes. 66 """ 67 68 __slots__ = ("_net",) 69 70 def __init__(self, net: traits.Netrunner) -> None: 71 self._net = net 72 73 def deserialize_bungie_user(self, data: typedefs.JSONObject) -> user.BungieUser: 74 return user.BungieUser( 75 id=int(data["membershipId"]), 76 created_at=time.clean_date(data["firstAccess"]), 77 name=data.get("cachedBungieGlobalDisplayName", undefined.UNDEFINED), 78 is_deleted=data["isDeleted"], 79 about=data["about"], 80 updated_at=time.clean_date(data["lastUpdate"]), 81 psn_name=data.get("psnDisplayName", None), 82 stadia_name=data.get("stadiaDisplayName", None), 83 steam_name=data.get("steamDisplayName", None), 84 twitch_name=data.get("twitchDisplayName", None), 85 blizzard_name=data.get("blizzardDisplayName", None), 86 status=data["statusText"], 87 locale=data["locale"], 88 picture=assets.Image(path=str(data["profilePicturePath"])), 89 code=data.get("cachedBungieGlobalDisplayNameCode", None), 90 unique_name=data.get("uniqueName", None), 91 theme_id=int(data["profileTheme"]), 92 show_activity=bool(data["showActivity"]), 93 theme_name=data["profileThemeName"], 94 display_title=data["userTitleDisplay"], 95 ) 96 97 def deserialize_partial_bungie_user( 98 self, payload: typedefs.JSONObject 99 ) -> user.PartialBungieUser: 100 return user.PartialBungieUser( 101 net=self._net, 102 types=[ 103 enums.MembershipType(type_) 104 for type_ in payload.get("applicableMembershipTypes", []) 105 ], 106 name=payload.get("displayName", undefined.UNDEFINED), 107 id=int(payload["membershipId"]), 108 crossave_override=enums.MembershipType(payload["crossSaveOverride"]), 109 is_public=payload["isPublic"], 110 icon=assets.Image(payload.get("iconPath", "")), 111 type=enums.MembershipType(payload["membershipType"]), 112 ) 113 114 def deserialize_destiny_membership( 115 self, payload: typedefs.JSONObject 116 ) -> user.DestinyMembership: 117 name: undefined.UndefinedOr[str] = undefined.UNDEFINED 118 if ( 119 raw_name := payload.get("bungieGlobalDisplayName", "") 120 ) and not typedefs.is_unknown(raw_name): 121 name = raw_name 122 123 return user.DestinyMembership( 124 net=self._net, 125 id=int(payload["membershipId"]), 126 name=name, 127 code=payload.get("bungieGlobalDisplayNameCode", None), 128 last_seen_name=payload.get("LastSeenDisplayName") 129 or payload.get("displayName") # noqa: W503 130 or "", # noqa: W503 131 type=enums.MembershipType(payload["membershipType"]), 132 is_public=payload["isPublic"], 133 crossave_override=enums.MembershipType(payload["crossSaveOverride"]), 134 icon=assets.Image(payload.get("iconPath", "")), 135 types=[ 136 enums.MembershipType(type_) 137 for type_ in payload.get("applicableMembershipTypes", []) 138 ], 139 ) 140 141 def deserialize_destiny_memberships( 142 self, data: typedefs.JSONArray 143 ) -> collections.Sequence[user.DestinyMembership]: 144 return [self.deserialize_destiny_membership(membership) for membership in data] 145 146 def deserialize_user(self, data: typedefs.JSONObject) -> user.User: 147 primary_membership_id: typing.Optional[int] = None 148 if raw_primary_id := data.get("primaryMembershipId"): 149 primary_membership_id = int(raw_primary_id) 150 151 return user.User( 152 bungie=self.deserialize_bungie_user(data["bungieNetUser"]), 153 destiny=self.deserialize_destiny_memberships(data["destinyMemberships"]), 154 primary_membership_id=primary_membership_id, 155 ) 156 157 def deserialize_searched_user( 158 self, payload: typedefs.JSONObject 159 ) -> user.SearchableDestinyUser: 160 name: undefined.UndefinedOr[str] = undefined.UNDEFINED 161 if (raw_name := payload["bungieGlobalDisplayName"]) and not typedefs.is_unknown( 162 raw_name 163 ): 164 name = raw_name 165 166 code: typing.Optional[int] = None 167 if raw_code := payload.get("bungieGlobalDisplayNameCode"): 168 code = int(raw_code) 169 170 bungie_id: typing.Optional[int] = None 171 if raw_bungie_id := payload.get("bungieNetMembershipId"): 172 bungie_id = int(raw_bungie_id) 173 174 return user.SearchableDestinyUser( 175 name=name, 176 code=code, 177 bungie_id=bungie_id, 178 memberships=self.deserialize_destiny_memberships( 179 payload["destinyMemberships"] 180 ), 181 ) 182 183 def deserialize_user_credentials( 184 self, payload: typedefs.JSONArray 185 ) -> collections.Sequence[user.UserCredentials]: 186 return [ 187 user.UserCredentials( 188 type=enums.CredentialType(int(creds["credentialType"])), 189 display_name=creds["credentialDisplayName"], 190 is_public=creds["isPublic"], 191 self_as_string=creds.get("credentialAsString", undefined.UNDEFINED), 192 ) 193 for creds in payload 194 ] 195 196 def deserialize_user_themes( 197 self, payload: typedefs.JSONArray 198 ) -> collections.Sequence[user.UserThemes]: 199 return [ 200 user.UserThemes( 201 id=int(entry["userThemeId"]), 202 name=entry["userThemeName"] 203 if "userThemeName" in entry 204 else undefined.UNDEFINED, 205 description=entry["userThemeDescription"] 206 if "userThemeDescription" in entry 207 else undefined.UNDEFINED, 208 ) 209 for entry in payload 210 ] 211 212 def deserialize_clan(self, payload: typedefs.JSONObject) -> clans.Clan: 213 # This is kinda redundant 214 data = payload 215 216 # This is always outside the details. 217 current_user_map: typing.Optional[ 218 collections.Mapping[str, clans.ClanMember] 219 ] = None 220 if raw_current_user_map := payload.get("currentUserMemberMap"): 221 current_user_map = { 222 membership_type: self.deserialize_clan_member(membership) 223 for membership_type, membership in raw_current_user_map.items() 224 } 225 226 try: 227 data = payload["detail"] 228 except KeyError: 229 pass 230 231 id = data["groupId"] 232 name = data["name"] 233 created_at = data["creationDate"] 234 member_count = data["memberCount"] 235 about = data["about"] 236 motto = data["motto"] 237 is_public = data["isPublic"] 238 banner = assets.Image(str(data["bannerPath"])) 239 avatar = assets.Image(str(data["avatarPath"])) 240 tags = data["tags"] 241 type = data["groupType"] 242 243 features = data["features"] 244 features_obj = clans.ClanFeatures( 245 max_members=features["maximumMembers"], 246 max_membership_types=features["maximumMembershipsOfGroupType"], 247 capabilities=features["capabilities"], 248 membership_types=features["membershipTypes"], 249 invite_permissions=features["invitePermissionOverride"], 250 update_banner_permissions=features["updateBannerPermissionOverride"], 251 update_culture_permissions=features["updateCulturePermissionOverride"], 252 join_level=features["joinLevel"], 253 ) 254 255 information: typedefs.JSONObject = data["clanInfo"] 256 progression: collections.Mapping[int, progressions.Progression] = { 257 int(prog_hash): self.deserialize_progressions(prog) 258 for prog_hash, prog in information["d2ClanProgressions"].items() 259 } 260 261 founder: typedefs.NoneOr[clans.ClanMember] = None 262 if raw_founder := payload.get("founder"): 263 founder = self.deserialize_clan_member(raw_founder) 264 265 return clans.Clan( 266 net=self._net, 267 id=int(id), 268 name=name, 269 type=enums.GroupType(type), 270 created_at=time.clean_date(created_at), 271 member_count=member_count, 272 motto=motto, 273 about=about, 274 is_public=is_public, 275 banner=banner, 276 avatar=avatar, 277 tags=tags, 278 features=features_obj, 279 owner=founder, 280 progressions=progression, 281 call_sign=information["clanCallsign"], 282 banner_data=information["clanBannerData"], 283 chat_security=data["chatSecurity"], 284 conversation_id=int(data["conversationId"]), 285 allow_chat=data["allowChat"], 286 theme=data["theme"], 287 current_user_membership=current_user_map, 288 ) 289 290 def deserialize_clan_member(self, data: typedefs.JSONObject, /) -> clans.ClanMember: 291 destiny_user = self.deserialize_destiny_membership(data["destinyUserInfo"]) 292 return clans.ClanMember( 293 net=self._net, 294 last_seen_name=destiny_user.last_seen_name, 295 id=destiny_user.id, 296 name=destiny_user.name, 297 icon=destiny_user.icon, 298 last_online=time.from_timestamp(int(data["lastOnlineStatusChange"])), 299 group_id=int(data["groupId"]), 300 joined_at=time.clean_date(data["joinDate"]), 301 types=destiny_user.types, 302 is_public=destiny_user.is_public, 303 type=destiny_user.type, 304 code=destiny_user.code, 305 is_online=data["isOnline"], 306 crossave_override=destiny_user.crossave_override, 307 bungie=self.deserialize_partial_bungie_user(data["bungieNetUserInfo"]) 308 if "bungieNetUserInfo" in data 309 else None, 310 member_type=enums.ClanMemberType(int(data["memberType"])), 311 ) 312 313 def deserialize_clan_members( 314 self, data: typedefs.JSONObject, / 315 ) -> iterators.Iterator[clans.ClanMember]: 316 return iterators.Iterator( 317 [self.deserialize_clan_member(member) for member in data["results"]] 318 ) 319 320 def deserialize_group_member( 321 self, payload: typedefs.JSONObject 322 ) -> clans.GroupMember: 323 member = payload["member"] 324 return clans.GroupMember( 325 net=self._net, 326 join_date=time.clean_date(member["joinDate"]), 327 group_id=int(member["groupId"]), 328 member_type=enums.ClanMemberType(member["memberType"]), 329 is_online=member["isOnline"], 330 last_online=time.from_timestamp(int(member["lastOnlineStatusChange"])), 331 inactive_memberships=payload.get("areAllMembershipsInactive", None), 332 member=self.deserialize_destiny_membership(member["destinyUserInfo"]), 333 group=self.deserialize_clan(payload["group"]), 334 ) 335 336 def _deserialize_clan_conversation( 337 self, payload: typedefs.JSONObject 338 ) -> clans.ClanConversation: 339 return clans.ClanConversation( 340 net=self._net, 341 id=int(payload["conversationId"]), 342 group_id=int(payload["groupId"]), 343 name=( 344 payload["chatName"] 345 if not typedefs.is_unknown(payload["chatName"]) 346 else undefined.UNDEFINED 347 ), 348 chat_enabled=payload["chatEnabled"], 349 security=payload["chatSecurity"], 350 ) 351 352 def deserialize_clan_conversations( 353 self, payload: typedefs.JSONArray 354 ) -> collections.Sequence[clans.ClanConversation]: 355 return [self._deserialize_clan_conversation(conv) for conv in payload] 356 357 def deserialize_app_owner( 358 self, payload: typedefs.JSONObject 359 ) -> application.ApplicationOwner: 360 return application.ApplicationOwner( 361 net=self._net, 362 name=payload.get("bungieGlobalDisplayName", undefined.UNDEFINED), 363 id=int(payload["membershipId"]), 364 type=enums.MembershipType(payload["membershipType"]), 365 icon=assets.Image(str(payload["iconPath"])), 366 is_public=payload["isPublic"], 367 code=payload.get("bungieGlobalDisplayNameCode", None), 368 ) 369 370 def deserialize_app(self, payload: typedefs.JSONObject) -> application.Application: 371 return application.Application( 372 id=int(payload["applicationId"]), 373 name=payload["name"], 374 link=payload["link"], 375 status=payload["status"], 376 redirect_url=payload.get("redirectUrl", None), 377 created_at=time.clean_date(str(payload["creationDate"])), 378 published_at=time.clean_date(str(payload["firstPublished"])), 379 owner=self.deserialize_app_owner(payload["team"][0]["user"]), # type: ignore 380 scope=payload.get("scope", undefined.UNDEFINED), 381 ) 382 383 def _set_character_attrs(self, payload: typedefs.JSONObject) -> character.Character: 384 total_time = time.format_played(int(payload["minutesPlayedTotal"]), suffix=True) 385 return character.Character( 386 net=self._net, 387 id=int(payload["characterId"]), 388 gender=enums.Gender(payload["genderType"]), 389 race=enums.Race(payload["raceType"]), 390 class_type=enums.Class(payload["classType"]), 391 emblem=assets.Image(str(payload["emblemBackgroundPath"])), 392 emblem_icon=assets.Image(str(payload["emblemPath"])), 393 emblem_hash=int(payload["emblemHash"]), 394 last_played=time.clean_date(payload["dateLastPlayed"]), 395 total_played_time=total_time, 396 member_id=int(payload["membershipId"]), 397 member_type=enums.MembershipType(payload["membershipType"]), 398 level=payload["baseCharacterLevel"], 399 title_hash=payload.get("titleRecordHash", None), 400 light=payload["light"], 401 stats={enums.Stat(int(k)): v for k, v in payload["stats"].items()}, 402 ) 403 404 def deserialize_profile(self, payload: typedefs.JSONObject, /) -> profile.Profile: 405 payload = payload["data"] 406 id = int(payload["userInfo"]["membershipId"]) 407 name = payload["userInfo"]["displayName"] 408 is_public = payload["userInfo"]["isPublic"] 409 type = enums.MembershipType(payload["userInfo"]["membershipType"]) 410 last_played = time.clean_date(str(payload["dateLastPlayed"])) 411 character_ids = [int(cid) for cid in payload["characterIds"]] 412 power_cap = payload["currentSeasonRewardPowerCap"] 413 414 return profile.Profile( 415 id=int(id), 416 name=name, 417 is_public=is_public, 418 type=type, 419 last_played=last_played, 420 character_ids=character_ids, 421 power_cap=power_cap, 422 net=self._net, 423 ) 424 425 def deserialize_profile_item( 426 self, payload: typedefs.JSONObject 427 ) -> profile.ProfileItemImpl: 428 instance_id: typing.Optional[int] = None 429 if raw_instance_id := payload.get("itemInstanceId"): 430 instance_id = int(raw_instance_id) 431 432 version_number: typing.Optional[int] = None 433 if raw_version := payload.get("versionNumber"): 434 version_number = int(raw_version) 435 436 transfer_status = enums.TransferStatus(payload["transferStatus"]) 437 438 return profile.ProfileItemImpl( 439 net=self._net, 440 hash=payload["itemHash"], 441 quantity=payload["quantity"], 442 bind_status=enums.ItemBindStatus(payload["bindStatus"]), 443 location=enums.ItemLocation(payload["location"]), 444 bucket=payload["bucketHash"], 445 transfer_status=transfer_status, 446 lockable=payload["lockable"], 447 state=enums.ItemState(payload["state"]), 448 dismantel_permissions=payload["dismantlePermission"], 449 is_wrapper=payload["isWrapper"], 450 instance_id=instance_id, 451 version_number=version_number, 452 ornament_id=payload.get("overrideStyleItemHash"), 453 ) 454 455 def deserialize_objectives(self, payload: typedefs.JSONObject) -> records.Objective: 456 return records.Objective( 457 net=self._net, 458 hash=payload["objectiveHash"], 459 visible=payload["visible"], 460 complete=payload["complete"], 461 completion_value=payload["completionValue"], 462 progress=payload.get("progress"), 463 destination_hash=payload.get("destinationHash"), 464 activity_hash=payload.get("activityHash"), 465 ) 466 467 def deserialize_records( 468 self, 469 payload: typedefs.JSONObject, 470 scores: typing.Optional[records.RecordScores] = None, 471 **nodes: int, 472 ) -> records.Record: 473 objectives: typing.Optional[list[records.Objective]] = None 474 interval_objectives: typing.Optional[list[records.Objective]] = None 475 record_state: typedefs.IntAnd[records.RecordState] 476 477 record_state = records.RecordState(payload["state"]) 478 479 if raw_objs := payload.get("objectives"): 480 objectives = [self.deserialize_objectives(obj) for obj in raw_objs] 481 482 if raw_interval_objs := payload.get("intervalObjectives"): 483 interval_objectives = [ 484 self.deserialize_objectives(obj) for obj in raw_interval_objs 485 ] 486 487 return records.Record( 488 scores=scores, 489 categories_node_hash=nodes.get("categories_hash", undefined.UNDEFINED), 490 seals_node_hash=nodes.get("seals_hash", undefined.UNDEFINED), 491 state=record_state, 492 objectives=objectives, 493 interval_objectives=interval_objectives, 494 redeemed_count=payload.get("intervalsRedeemedCount", 0), 495 completion_times=payload.get("completedCount", None), 496 reward_visibility=payload.get("rewardVisibilty", None), 497 ) 498 499 def deserialize_character_records( 500 self, 501 payload: typedefs.JSONObject, 502 scores: typing.Optional[records.RecordScores] = None, 503 record_hashes: typing.Optional[list[int]] = None, 504 ) -> records.CharacterRecord: 505 record = self.deserialize_records(payload, scores) 506 return records.CharacterRecord( 507 scores=scores, 508 categories_node_hash=record.categories_node_hash, 509 seals_node_hash=record.seals_node_hash, 510 state=record.state, 511 objectives=record.objectives, 512 interval_objectives=record.interval_objectives, 513 redeemed_count=payload.get("intervalsRedeemedCount", 0), 514 completion_times=payload.get("completedCount"), 515 reward_visibility=payload.get("rewardVisibilty"), 516 record_hashes=record_hashes or [], 517 ) 518 519 def deserialize_character_dye(self, payload: typedefs.JSONObject) -> character.Dye: 520 return character.Dye( 521 channel_hash=payload["channelHash"], dye_hash=payload["dyeHash"] 522 ) 523 524 def deserialize_character_customization( 525 self, payload: typedefs.JSONObject 526 ) -> character.CustomizationOptions: 527 return character.CustomizationOptions( 528 personality=payload["personality"], 529 face=payload["face"], 530 skin_color=payload["skinColor"], 531 lip_color=payload["lipColor"], 532 eye_color=payload["eyeColor"], 533 hair_colors=payload.get("hairColors", []), 534 feature_colors=payload.get("featureColors", []), 535 decal_color=payload["decalColor"], 536 wear_helmet=payload["wearHelmet"], 537 hair_index=payload["hairIndex"], 538 feature_index=payload["featureIndex"], 539 decal_index=payload["decalIndex"], 540 ) 541 542 def deserialize_character_minimal_equipments( 543 self, payload: typedefs.JSONObject 544 ) -> character.MinimalEquipments: 545 dyes = None 546 if raw_dyes := payload.get("dyes"): 547 if raw_dyes: 548 dyes = [self.deserialize_character_dye(dye) for dye in raw_dyes] 549 return character.MinimalEquipments( 550 net=self._net, item_hash=payload["itemHash"], dyes=dyes 551 ) 552 553 def deserialize_character_render_data( 554 self, payload: typedefs.JSONObject, / 555 ) -> character.RenderedData: 556 return character.RenderedData( 557 net=self._net, 558 customization=self.deserialize_character_customization( 559 payload["customization"] 560 ), 561 custom_dyes=[ 562 self.deserialize_character_dye(dye) 563 for dye in payload["customDyes"] 564 if dye 565 ], 566 equipment=[ 567 self.deserialize_character_minimal_equipments(equipment) 568 for equipment in payload["peerView"]["equipment"] 569 ], 570 ) 571 572 def deserialize_available_activity( 573 self, payload: typedefs.JSONObject 574 ) -> activity.AvailableActivity: 575 return activity.AvailableActivity( 576 hash=payload["activityHash"], 577 is_new=payload["isNew"], 578 is_completed=payload["isCompleted"], 579 is_visible=payload["isVisible"], 580 display_level=payload.get("displayLevel"), 581 recommended_light=payload.get("recommendedLight"), 582 difficulty=activity.Difficulty(payload["difficultyTier"]), 583 can_join=payload["canJoin"], 584 can_lead=payload["canLead"], 585 ) 586 587 def deserialize_character_activity( 588 self, payload: typedefs.JSONObject 589 ) -> activity.CharacterActivity: 590 current_mode: typing.Optional[enums.GameMode] = None 591 if raw_current_mode := payload.get("currentActivityModeType"): 592 current_mode = enums.GameMode(raw_current_mode) 593 594 current_mode_types: typing.Optional[collections.Sequence[enums.GameMode]] = None 595 if raw_current_modes := payload.get("currentActivityModeTypes"): 596 current_mode_types = [enums.GameMode(type_) for type_ in raw_current_modes] 597 598 return activity.CharacterActivity( 599 date_started=time.clean_date(payload["dateActivityStarted"]), 600 current_hash=payload["currentActivityHash"], 601 current_mode_hash=payload["currentActivityModeHash"], 602 current_mode=current_mode, 603 current_mode_hashes=payload.get("currentActivityModeHashes"), 604 current_mode_types=current_mode_types, 605 current_playlist_hash=payload.get("currentPlaylistActivityHash"), 606 last_story_hash=payload["lastCompletedStoryHash"], 607 available_activities=[ 608 self.deserialize_available_activity(activity_) 609 for activity_ in payload["availableActivities"] 610 ], 611 ) 612 613 def deserialize_profile_items( 614 self, payload: typedefs.JSONObject, / 615 ) -> list[profile.ProfileItemImpl]: 616 return [self.deserialize_profile_item(item) for item in payload["items"]] 617 618 def _deserialize_node(self, payload: typedefs.JSONObject) -> records.Node: 619 return records.Node( 620 state=int(payload["state"]), 621 objective=self.deserialize_objectives(payload["objective"]) 622 if "objective" in payload 623 else None, 624 progress_value=int(payload["progressValue"]), 625 completion_value=int(payload["completionValue"]), 626 record_category_score=int(payload["recordCategoryScore"]) 627 if "recordCategoryScore" in payload 628 else None, 629 ) 630 631 @staticmethod 632 def _deserialize_collectible(payload: typedefs.JSONObject) -> items.Collectible: 633 recent_collectibles: typing.Optional[collections.Collection[int]] = None 634 if raw_recent_collectibles := payload.get("recentCollectibleHashes"): 635 recent_collectibles = [ 636 int(item_hash) for item_hash in raw_recent_collectibles 637 ] 638 639 collectibles: dict[int, int] = {} 640 for item_hash, mapping in payload["collectibles"].items(): 641 collectibles[int(item_hash)] = int(mapping["state"]) 642 643 return items.Collectible( 644 recent_collectibles=recent_collectibles, 645 collectibles=collectibles, 646 collection_categorie_hash=int(payload["collectionCategoriesRootNodeHash"]), 647 collection_badges_hash=int(payload["collectionBadgesRootNodeHash"]), 648 ) 649 650 @staticmethod 651 def _deserialize_currencies( 652 payload: typedefs.JSONObject, 653 ) -> collections.Sequence[items.Currency]: 654 return [ 655 items.Currency(hash=int(item_hash), amount=int(amount)) 656 for item_hash, amount in payload["itemQuantities"].items() 657 ] 658 659 def deserialize_progressions( 660 self, payload: typedefs.JSONObject 661 ) -> progressions.Progression: 662 return progressions.Progression( 663 hash=int(payload["progressionHash"]), 664 level=int(payload["level"]), 665 cap=int(payload["levelCap"]), 666 daily_limit=int(payload["dailyLimit"]), 667 weekly_limit=int(payload["weeklyLimit"]), 668 current_progress=int(payload["currentProgress"]), 669 daily_progress=int(payload["dailyProgress"]), 670 needed=int(payload["progressToNextLevel"]), 671 next_level=int(payload["nextLevelAt"]), 672 ) 673 674 def _deserialize_factions( 675 self, payload: typedefs.JSONObject 676 ) -> progressions.Factions: 677 progs = self.deserialize_progressions(payload) 678 return progressions.Factions( 679 hash=progs.hash, 680 level=progs.level, 681 cap=progs.cap, 682 daily_limit=progs.daily_limit, 683 weekly_limit=progs.weekly_limit, 684 current_progress=progs.current_progress, 685 daily_progress=progs.daily_progress, 686 needed=progs.needed, 687 next_level=progs.next_level, 688 faction_hash=payload["factionHash"], 689 faction_vendor_hash=payload["factionVendorIndex"], 690 ) 691 692 def _deserialize_milestone_available_quest( 693 self, payload: typedefs.JSONObject 694 ) -> milestones.MilestoneQuest: 695 return milestones.MilestoneQuest( 696 item_hash=payload["questItemHash"], 697 status=self._deserialize_milestone_quest_status(payload["status"]), 698 ) 699 700 def _deserialize_milestone_activity( 701 self, payload: typedefs.JSONObject 702 ) -> milestones.MilestoneActivity: 703 phases: typing.Optional[ 704 collections.Sequence[milestones.MilestoneActivityPhase] 705 ] = None 706 if raw_phases := payload.get("phases"): 707 phases = [ 708 milestones.MilestoneActivityPhase( 709 is_completed=obj["complete"], hash=obj["phaseHash"] 710 ) 711 for obj in raw_phases 712 ] 713 714 return milestones.MilestoneActivity( 715 hash=payload["activityHash"], 716 challenges=[ 717 self.deserialize_objectives(obj["objective"]) 718 for obj in payload["challenges"] 719 ], 720 modifier_hashes=payload.get("modifierHashes"), 721 boolean_options=payload.get("booleanActivityOptions"), 722 phases=phases, 723 ) 724 725 def _deserialize_milestone_quest_status( 726 self, payload: typedefs.JSONObject 727 ) -> milestones.QuestStatus: 728 return milestones.QuestStatus( 729 net=self._net, 730 quest_hash=payload["questHash"], 731 step_hash=payload["stepHash"], 732 step_objectives=[ 733 self.deserialize_objectives(objective) 734 for objective in payload["stepObjectives"] 735 ], 736 is_tracked=payload["tracked"], 737 is_completed=payload["completed"], 738 started=payload["started"], 739 item_instance_id=payload["itemInstanceId"], 740 vendor_hash=payload.get("vendorHash"), 741 is_redeemed=payload["redeemed"], 742 ) 743 744 def _deserialize_milestone_rewards( 745 self, payload: typedefs.JSONObject 746 ) -> milestones.MilestoneReward: 747 return milestones.MilestoneReward( 748 category_hash=payload["rewardCategoryHash"], 749 entries=[ 750 milestones.MilestoneRewardEntry( 751 entry_hash=entry["rewardEntryHash"], 752 is_earned=entry["earned"], 753 is_redeemed=entry["redeemed"], 754 ) 755 for entry in payload["entries"] 756 ], 757 ) 758 759 def deserialize_milestone( 760 self, payload: typedefs.JSONObject 761 ) -> milestones.Milestone: 762 start_date: typing.Optional[datetime.datetime] = None 763 if raw_start_date := payload.get("startDate"): 764 start_date = time.clean_date(raw_start_date) 765 766 end_date: typing.Optional[datetime.datetime] = None 767 if raw_end_date := payload.get("endDate"): 768 end_date = time.clean_date(raw_end_date) 769 770 rewards: typing.Optional[ 771 collections.Collection[milestones.MilestoneReward] 772 ] = None 773 if raw_rewards := payload.get("rewards"): 774 rewards = [ 775 self._deserialize_milestone_rewards(reward) for reward in raw_rewards 776 ] 777 778 activities: typing.Optional[ 779 collections.Sequence[milestones.MilestoneActivity] 780 ] = None 781 if raw_activities := payload.get("activities"): 782 activities = [ 783 self._deserialize_milestone_activity(active) 784 for active in raw_activities 785 ] 786 787 quests: typing.Optional[collections.Sequence[milestones.MilestoneQuest]] = None 788 if raw_quests := payload.get("availableQuests"): 789 quests = [ 790 self._deserialize_milestone_available_quest(quest) 791 for quest in raw_quests 792 ] 793 794 vendors: typing.Optional[ 795 collections.Sequence[milestones.MilestoneVendor] 796 ] = None 797 if raw_vendors := payload.get("vendors"): 798 vendors = [ 799 milestones.MilestoneVendor( 800 vendor_hash=vendor["vendorHash"], 801 preview_itemhash=vendor.get("previewItemHash"), 802 ) 803 for vendor in raw_vendors 804 ] 805 806 return milestones.Milestone( 807 hash=payload["milestoneHash"], 808 start_date=start_date, 809 end_date=end_date, 810 order=payload["order"], 811 rewards=rewards, 812 available_quests=quests, 813 activities=activities, 814 vendors=vendors, 815 ) 816 817 def _deserialize_artifact_tiers( 818 self, payload: typedefs.JSONObject 819 ) -> season.ArtifactTier: 820 return season.ArtifactTier( 821 hash=payload["tierHash"], 822 is_unlocked=payload["isUnlocked"], 823 points_to_unlock=payload["pointsToUnlock"], 824 items=[ 825 season.ArtifactTierItem( 826 hash=item["itemHash"], is_active=item["isActive"] 827 ) 828 for item in payload["items"] 829 ], 830 ) 831 832 def deserialize_characters( 833 self, payload: typedefs.JSONObject 834 ) -> collections.Mapping[int, character.Character]: 835 return { 836 int(char_id): self._set_character_attrs(char) 837 for char_id, char in payload["data"].items() 838 } 839 840 def deserialize_character( 841 self, payload: typedefs.JSONObject 842 ) -> character.Character: 843 return self._set_character_attrs(payload) 844 845 def deserialize_character_equipments( 846 self, payload: typedefs.JSONObject 847 ) -> collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]]: 848 return { 849 int(char_id): self.deserialize_profile_items(item) 850 for char_id, item in payload["data"].items() 851 } 852 853 def deserialize_character_activities( 854 self, payload: typedefs.JSONObject 855 ) -> collections.Mapping[int, activity.CharacterActivity]: 856 return { 857 int(char_id): self.deserialize_character_activity(data) 858 for char_id, data in payload["data"].items() 859 } 860 861 def deserialize_characters_render_data( 862 self, payload: typedefs.JSONObject 863 ) -> collections.Mapping[int, character.RenderedData]: 864 return { 865 int(char_id): self.deserialize_character_render_data(data) 866 for char_id, data in payload["data"].items() 867 } 868 869 def deserialize_character_progressions( 870 self, payload: typedefs.JSONObject 871 ) -> character.CharacterProgression: 872 progressions_ = { 873 int(prog_id): self.deserialize_progressions(prog) 874 for prog_id, prog in payload["progressions"].items() 875 } 876 877 factions = { 878 int(faction_id): self._deserialize_factions(faction) 879 for faction_id, faction in payload["factions"].items() 880 } 881 882 milestones_ = { 883 int(milestone_hash): self.deserialize_milestone(milestone) 884 for milestone_hash, milestone in payload["milestones"].items() 885 } 886 887 uninstanced_item_objectives = { 888 int(item_hash): [self.deserialize_objectives(ins) for ins in obj] 889 for item_hash, obj in payload["uninstancedItemObjectives"].items() 890 } 891 892 artifact = payload["seasonalArtifact"] 893 seasonal_artifact = season.CharacterScopedArtifact( 894 hash=artifact["artifactHash"], 895 points_used=artifact["pointsUsed"], 896 reset_count=artifact["resetCount"], 897 tiers=[ 898 self._deserialize_artifact_tiers(tier) for tier in artifact["tiers"] 899 ], 900 ) 901 checklists = payload["checklists"] 902 903 return character.CharacterProgression( 904 progressions=progressions_, 905 factions=factions, 906 checklists=checklists, 907 milestones=milestones_, 908 seasonal_artifact=seasonal_artifact, 909 uninstanced_item_objectives=uninstanced_item_objectives, 910 ) 911 912 def deserialize_character_progressions_mapping( 913 self, payload: typedefs.JSONObject 914 ) -> collections.Mapping[int, character.CharacterProgression]: 915 character_progressions: collections.Mapping[ 916 int, character.CharacterProgression 917 ] = {} 918 for char_id, data in payload["data"].items(): 919 # A little hack to stop mypy complaining about Mapping <-> dict 920 character_progressions[int(char_id)] = self.deserialize_character_progressions(data) # type: ignore[index] 921 return character_progressions 922 923 def deserialize_characters_records( 924 self, 925 payload: typedefs.JSONObject, 926 ) -> collections.Mapping[int, records.CharacterRecord]: 927 return { 928 int(rec_id): self.deserialize_character_records( 929 rec, record_hashes=payload.get("featuredRecordHashes") 930 ) 931 for rec_id, rec in payload["records"].items() 932 } 933 934 def deserialize_profile_records( 935 self, payload: typedefs.JSONObject 936 ) -> collections.Mapping[int, records.Record]: 937 raw_profile_records = payload["data"] 938 scores = records.RecordScores( 939 current_score=raw_profile_records["score"], 940 legacy_score=raw_profile_records["legacyScore"], 941 lifetime_score=raw_profile_records["lifetimeScore"], 942 ) 943 return { 944 int(record_id): self.deserialize_records( 945 record, 946 scores, 947 categories_hash=raw_profile_records["recordCategoriesRootNodeHash"], 948 seals_hash=raw_profile_records["recordSealsRootNodeHash"], 949 ) 950 for record_id, record in raw_profile_records["records"].items() 951 } 952 953 def _deserialize_craftable_socket_plug( 954 self, payload: typedefs.JSONObject 955 ) -> items.CraftableSocketPlug: 956 return items.CraftableSocketPlug( 957 item_hash=int(payload["plugItemHash"]), 958 failed_requirement_indexes=payload.get("failedRequirementIndexes", []), 959 ) 960 961 def _deserialize_craftable_socket( 962 self, payload: typedefs.JSONObject 963 ) -> items.CraftableSocket: 964 plugs: list[items.CraftableSocketPlug] = [] 965 if raw_plug := payload.get("plug"): 966 plugs.extend( 967 self._deserialize_craftable_socket_plug(plug) for plug in raw_plug 968 ) 969 970 return items.CraftableSocket( 971 plug_set_hash=int(payload["plugSetHash"]), plugs=plugs 972 ) 973 974 def _deserialize_craftable_item( 975 self, payload: typedefs.JSONObject 976 ) -> items.CraftableItem: 977 return items.CraftableItem( 978 is_visible=payload["visible"], 979 failed_requirement_indexes=payload.get("failedRequirementIndexes", []), 980 sockets=[ 981 self._deserialize_craftable_socket(socket) 982 for socket in payload["sockets"] 983 ], 984 ) 985 986 def deserialize_craftables_component( 987 self, payload: typedefs.JSONObject 988 ) -> components.CraftablesComponent: 989 return components.CraftablesComponent( 990 net=self._net, 991 craftables={ 992 int(item_id): self._deserialize_craftable_item(item) 993 for item_id, item in payload["craftables"].items() 994 if item is not None 995 }, 996 crafting_root_node_hash=payload["craftingRootNodeHash"], 997 ) 998 999 def deserialize_components( # noqa: C901 Too complex. 1000 self, payload: typedefs.JSONObject 1001 ) -> components.Component: 1002 profile_: typing.Optional[profile.Profile] = None 1003 if raw_profile := payload.get("profile"): 1004 profile_ = self.deserialize_profile(raw_profile) 1005 1006 profile_progression: typing.Optional[profile.ProfileProgression] = None 1007 if raw_profile_progression := payload.get("profileProgression"): 1008 profile_progression = self.deserialize_profile_progression( 1009 raw_profile_progression 1010 ) 1011 1012 profile_currencies: typing.Optional[ 1013 collections.Sequence[profile.ProfileItemImpl] 1014 ] = None 1015 if raw_profile_currencies := payload.get("profileCurrencies"): 1016 if "data" in raw_profile_currencies: 1017 profile_currencies = self.deserialize_profile_items( 1018 raw_profile_currencies["data"] 1019 ) 1020 1021 profile_inventories: typing.Optional[ 1022 collections.Sequence[profile.ProfileItemImpl] 1023 ] = None 1024 if raw_profile_inventories := payload.get("profileInventory"): 1025 if "data" in raw_profile_inventories: 1026 profile_inventories = self.deserialize_profile_items( 1027 raw_profile_inventories["data"] 1028 ) 1029 1030 profile_records: typing.Optional[ 1031 collections.Mapping[int, records.Record] 1032 ] = None 1033 1034 if raw_profile_records_ := payload.get("profileRecords"): 1035 profile_records = self.deserialize_profile_records(raw_profile_records_) 1036 1037 characters: typing.Optional[typing.Mapping[int, character.Character]] = None 1038 if raw_characters := payload.get("characters"): 1039 characters = self.deserialize_characters(raw_characters) 1040 1041 character_records: typing.Optional[ 1042 collections.Mapping[int, records.CharacterRecord] 1043 ] = None 1044 1045 if raw_character_records := payload.get("characterRecords"): 1046 # Had to do it in two steps.. 1047 to_update: typedefs.JSONObject = {} 1048 for _, data in raw_character_records["data"].items(): 1049 for record_id, record in data.items(): 1050 to_update[record_id] = record 1051 1052 character_records = { 1053 int(rec_id): self.deserialize_character_records( 1054 rec, record_hashes=to_update.get("featuredRecordHashes") 1055 ) 1056 for rec_id, rec in to_update["records"].items() 1057 } 1058 1059 character_equipments: typing.Optional[ 1060 collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]] 1061 ] = None 1062 if raw_character_equips := payload.get("characterEquipment"): 1063 character_equipments = self.deserialize_character_equipments( 1064 raw_character_equips 1065 ) 1066 1067 character_inventories: typing.Optional[ 1068 collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]] 1069 ] = None 1070 if raw_character_inventories := payload.get("characterInventories"): 1071 if "data" in raw_character_inventories: 1072 character_inventories = self.deserialize_character_equipments( 1073 raw_character_inventories 1074 ) 1075 1076 character_activities: typing.Optional[ 1077 collections.Mapping[int, activity.CharacterActivity] 1078 ] = None 1079 if raw_char_acts := payload.get("characterActivities"): 1080 character_activities = self.deserialize_character_activities(raw_char_acts) 1081 1082 character_render_data: typing.Optional[ 1083 collections.Mapping[int, character.RenderedData] 1084 ] = None 1085 if raw_character_render_data := payload.get("characterRenderData"): 1086 character_render_data = self.deserialize_characters_render_data( 1087 raw_character_render_data 1088 ) 1089 1090 character_progressions: typing.Optional[ 1091 collections.Mapping[int, character.CharacterProgression] 1092 ] = None 1093 1094 if raw_character_progressions := payload.get("characterProgressions"): 1095 character_progressions = self.deserialize_character_progressions_mapping( 1096 raw_character_progressions 1097 ) 1098 1099 profile_string_vars: typing.Optional[collections.Mapping[int, int]] = None 1100 if raw_profile_string_vars := payload.get("profileStringVariables"): 1101 profile_string_vars = raw_profile_string_vars["data"]["integerValuesByHash"] 1102 1103 character_string_vars: typing.Optional[ 1104 collections.Mapping[int, collections.Mapping[int, int]] 1105 ] = None 1106 if raw_character_string_vars := payload.get("characterStringVariables"): 1107 character_string_vars = { 1108 int(char_id): data["integerValuesByHash"] 1109 for char_id, data in raw_character_string_vars["data"].items() 1110 } 1111 1112 metrics: typing.Optional[ 1113 collections.Sequence[ 1114 collections.Mapping[ 1115 int, tuple[bool, typing.Optional[records.Objective]] 1116 ] 1117 ] 1118 ] = None 1119 root_node_hash: typing.Optional[int] = None 1120 1121 if raw_metrics := payload.get("metrics"): 1122 root_node_hash = raw_metrics["data"]["metricsRootNodeHash"] 1123 metrics = [ 1124 { 1125 int(metrics_hash): ( 1126 data["invisible"], 1127 self.deserialize_objectives(data["objectiveProgress"]) 1128 if "objectiveProgress" in data 1129 else None, 1130 ) 1131 for metrics_hash, data in raw_metrics["data"]["metrics"].items() 1132 } 1133 ] 1134 transitory: typing.Optional[fireteams.FireteamParty] = None 1135 if raw_transitory := payload.get("profileTransitoryData"): 1136 if "data" in raw_transitory: 1137 transitory = self.deserialize_fireteam_party(raw_transitory["data"]) 1138 1139 item_components: typing.Optional[components.ItemsComponent] = None 1140 if raw_item_components := payload.get("itemComponents"): 1141 item_components = self.deserialize_items_component(raw_item_components) 1142 1143 profile_plugsets: typing.Optional[ 1144 collections.Mapping[int, collections.Sequence[items.PlugItemState]] 1145 ] = None 1146 1147 if raw_profile_plugs := payload.get("profilePlugSets"): 1148 profile_plugsets = { 1149 int(index): [self.deserialize_plug_item_state(state) for state in data] 1150 for index, data in raw_profile_plugs["data"]["plugs"].items() 1151 } 1152 1153 character_plugsets: typing.Optional[ 1154 collections.Mapping[ 1155 int, collections.Mapping[int, collections.Sequence[items.PlugItemState]] 1156 ] 1157 ] = None 1158 if raw_char_plugsets := payload.get("characterPlugSets"): 1159 character_plugsets = { 1160 int(char_id): { 1161 int(index): [ 1162 self.deserialize_plug_item_state(state) for state in data 1163 ] 1164 for index, data in inner["plugs"].items() 1165 } 1166 for char_id, inner in raw_char_plugsets["data"].items() 1167 } 1168 1169 character_collectibles: typing.Optional[ 1170 collections.Mapping[int, items.Collectible] 1171 ] = None 1172 if raw_character_collectibles := payload.get("characterCollectibles"): 1173 character_collectibles = { 1174 int(char_id): self._deserialize_collectible(data) 1175 for char_id, data in raw_character_collectibles["data"].items() 1176 } 1177 1178 profile_collectibles: typing.Optional[items.Collectible] = None 1179 if raw_profile_collectibles := payload.get("profileCollectibles"): 1180 profile_collectibles = self._deserialize_collectible( 1181 raw_profile_collectibles["data"] 1182 ) 1183 1184 profile_nodes: typing.Optional[collections.Mapping[int, records.Node]] = None 1185 if raw_profile_nodes := payload.get("profilePresentationNodes"): 1186 profile_nodes = { 1187 int(node_hash): self._deserialize_node(node) 1188 for node_hash, node in raw_profile_nodes["data"]["nodes"].items() 1189 } 1190 1191 character_nodes: typing.Optional[ 1192 collections.Mapping[int, collections.Mapping[int, records.Node]] 1193 ] = None 1194 if raw_character_nodes := payload.get("characterPresentationNodes"): 1195 character_nodes = { 1196 int(char_id): { 1197 int(node_hash): self._deserialize_node(node) 1198 for node_hash, node in each_character["nodes"].items() 1199 } 1200 for char_id, each_character in raw_character_nodes["data"].items() 1201 } 1202 1203 platform_silver: typing.Optional[ 1204 collections.Mapping[str, profile.ProfileItemImpl] 1205 ] = None 1206 if raw_platform_silver := payload.get("platformSilver"): 1207 if "data" in raw_platform_silver: 1208 platform_silver = { 1209 platform_name: self.deserialize_profile_item(item) 1210 for platform_name, item in raw_platform_silver["data"][ 1211 "platformSilver" 1212 ].items() 1213 } 1214 1215 character_currency_lookups: typing.Optional[ 1216 collections.Mapping[int, collections.Sequence[items.Currency]] 1217 ] = None 1218 if raw_char_lookups := payload.get("characterCurrencyLookups"): 1219 if "data" in raw_char_lookups: 1220 character_currency_lookups = { 1221 int(char_id): self._deserialize_currencies(currencie) 1222 for char_id, currencie in raw_char_lookups["data"].items() 1223 } 1224 1225 character_craftables: typing.Optional[ 1226 collections.Mapping[int, components.CraftablesComponent] 1227 ] = None 1228 if raw_character_craftables := payload.get("characterCraftables"): 1229 if "data" in raw_character_craftables: 1230 character_craftables = { 1231 int(char_id): self.deserialize_craftables_component(craftable) 1232 for char_id, craftable in raw_character_craftables["data"].items() 1233 } 1234 1235 return components.Component( 1236 profiles=profile_, 1237 profile_progression=profile_progression, 1238 profile_currencies=profile_currencies, 1239 profile_inventories=profile_inventories, 1240 profile_records=profile_records, 1241 characters=characters, 1242 character_records=character_records, 1243 character_equipments=character_equipments, 1244 character_inventories=character_inventories, 1245 character_activities=character_activities, 1246 character_render_data=character_render_data, 1247 character_progressions=character_progressions, 1248 profile_string_variables=profile_string_vars, 1249 character_string_variables=character_string_vars, 1250 metrics=metrics, 1251 root_node_hash=root_node_hash, 1252 transitory=transitory, 1253 item_components=item_components, 1254 profile_plugsets=profile_plugsets, 1255 character_plugsets=character_plugsets, 1256 character_collectibles=character_collectibles, 1257 profile_collectibles=profile_collectibles, 1258 profile_nodes=profile_nodes, 1259 character_nodes=character_nodes, 1260 platform_silver=platform_silver, 1261 character_currency_lookups=character_currency_lookups, 1262 character_craftables=character_craftables, 1263 ) 1264 1265 def deserialize_items_component( 1266 self, payload: typedefs.JSONObject 1267 ) -> components.ItemsComponent: 1268 instances: typing.Optional[ 1269 collections.Sequence[collections.Mapping[int, items.ItemInstance]] 1270 ] = None 1271 if raw_instances := payload.get("instances"): 1272 instances = [ 1273 { 1274 int(ins_id): self.deserialize_instanced_item(item) 1275 for ins_id, item in raw_instances["data"].items() 1276 } 1277 ] 1278 1279 render_data: typing.Optional[ 1280 collections.Mapping[int, tuple[bool, dict[int, int]]] 1281 ] = None 1282 if raw_render_data := payload.get("renderData"): 1283 render_data = { 1284 int(ins_id): (data["useCustomDyes"], data["artRegions"]) 1285 for ins_id, data in raw_render_data["data"].items() 1286 } 1287 1288 stats: typing.Optional[collections.Mapping[int, items.ItemStatsView]] = None 1289 if raw_stats := payload.get("stats"): 1290 builder: collections.Mapping[int, items.ItemStatsView] = {} 1291 for ins_id, stat in raw_stats["data"].items(): 1292 for _, items_ in stat.items(): 1293 builder[int(ins_id)] = self.deserialize_item_stats_view(items_) # type: ignore[index] 1294 stats = builder 1295 1296 sockets: typing.Optional[ 1297 collections.Mapping[int, collections.Sequence[items.ItemSocket]] 1298 ] = None 1299 if raw_sockets := payload.get("sockets"): 1300 sockets = { 1301 int(ins_id): [ 1302 self.deserialize_item_socket(socket) for socket in item["sockets"] 1303 ] 1304 for ins_id, item in raw_sockets["data"].items() 1305 } 1306 1307 objeectives: typing.Optional[ 1308 collections.Mapping[int, collections.Sequence[records.Objective]] 1309 ] = None 1310 if raw_objectives := payload.get("objectives"): 1311 objeectives = { 1312 int(ins_id): [self.deserialize_objectives(objective)] 1313 for ins_id, data in raw_objectives["data"].items() 1314 for objective in data["objectives"] 1315 } 1316 1317 perks: typing.Optional[ 1318 collections.Mapping[int, collections.Collection[items.ItemPerk]] 1319 ] = None 1320 if raw_perks := payload.get("perks"): 1321 perks = { 1322 int(ins_id): [ 1323 self.deserialize_item_perk(perk) for perk in item["perks"] 1324 ] 1325 for ins_id, item in raw_perks["data"].items() 1326 } 1327 1328 plug_states: typing.Optional[collections.Sequence[items.PlugItemState]] = None 1329 if raw_plug_states := payload.get("plugStates"): 1330 pending_states: list[items.PlugItemState] = [] 1331 for _, plug in raw_plug_states["data"].items(): 1332 pending_states.append(self.deserialize_plug_item_state(plug)) 1333 plug_states = pending_states 1334 1335 reusable_plugs: typing.Optional[ 1336 collections.Mapping[int, collections.Sequence[items.PlugItemState]] 1337 ] = None 1338 if raw_re_plugs := payload.get("reusablePlugs"): 1339 reusable_plugs = { 1340 int(ins_id): [ 1341 self.deserialize_plug_item_state(state) for state in inner 1342 ] 1343 for ins_id, plug in raw_re_plugs["data"].items() 1344 for inner in list(plug["plugs"].values()) 1345 } 1346 1347 plug_objectives: typing.Optional[ 1348 collections.Mapping[ 1349 int, collections.Mapping[int, collections.Collection[records.Objective]] 1350 ] 1351 ] = None 1352 if raw_plug_objectives := payload.get("plugObjectives"): 1353 plug_objectives = { 1354 int(ins_id): { 1355 int(obj_hash): [self.deserialize_objectives(obj) for obj in objs] 1356 for obj_hash, objs in inner["objectivesPerPlug"].items() 1357 } 1358 for ins_id, inner in raw_plug_objectives["data"].items() 1359 } 1360 1361 return components.ItemsComponent( 1362 sockets=sockets, 1363 stats=stats, 1364 render_data=render_data, 1365 instances=instances, 1366 objectives=objeectives, 1367 perks=perks, 1368 plug_states=plug_states, 1369 reusable_plugs=reusable_plugs, 1370 plug_objectives=plug_objectives, 1371 ) 1372 1373 def deserialize_character_component( # type: ignore[call-arg] 1374 self, payload: typedefs.JSONObject 1375 ) -> components.CharacterComponent: 1376 character_: typing.Optional[character.Character] = None 1377 if raw_singuler_character := payload.get("character"): 1378 character_ = self.deserialize_character(raw_singuler_character["data"]) 1379 1380 inventory: typing.Optional[collections.Sequence[profile.ProfileItemImpl]] = None 1381 if raw_inventory := payload.get("inventory"): 1382 if "data" in raw_inventory: 1383 inventory = self.deserialize_profile_items(raw_inventory["data"]) 1384 1385 activities: typing.Optional[activity.CharacterActivity] = None 1386 if raw_activities := payload.get("activities"): 1387 activities = self.deserialize_character_activity(raw_activities["data"]) 1388 1389 equipment: typing.Optional[collections.Sequence[profile.ProfileItemImpl]] = None 1390 if raw_equipments := payload.get("equipment"): 1391 equipment = self.deserialize_profile_items(raw_equipments["data"]) 1392 1393 progressions_: typing.Optional[character.CharacterProgression] = None 1394 if raw_progressions := payload.get("progressions"): 1395 progressions_ = self.deserialize_character_progressions( 1396 raw_progressions["data"] 1397 ) 1398 1399 render_data: typing.Optional[character.RenderedData] = None 1400 if raw_render_data := payload.get("renderData"): 1401 render_data = self.deserialize_character_render_data( 1402 raw_render_data["data"] 1403 ) 1404 1405 character_records: typing.Optional[ 1406 collections.Mapping[int, records.CharacterRecord] 1407 ] = None 1408 if raw_char_records := payload.get("records"): 1409 character_records = self.deserialize_characters_records( 1410 raw_char_records["data"] 1411 ) 1412 1413 item_components: typing.Optional[components.ItemsComponent] = None 1414 if raw_item_components := payload.get("itemComponents"): 1415 item_components = self.deserialize_items_component(raw_item_components) 1416 1417 nodes: typing.Optional[collections.Mapping[int, records.Node]] = None 1418 if raw_nodes := payload.get("presentationNodes"): 1419 nodes = { 1420 int(node_hash): self._deserialize_node(node) 1421 for node_hash, node in raw_nodes["data"]["nodes"].items() 1422 } 1423 1424 collectibles: typing.Optional[items.Collectible] = None 1425 if raw_collectibles := payload.get("collectibles"): 1426 collectibles = self._deserialize_collectible(raw_collectibles["data"]) 1427 1428 currency_lookups: typing.Optional[collections.Sequence[items.Currency]] = None 1429 if raw_currencies := payload.get("currencyLookups"): 1430 if "data" in raw_currencies: 1431 currency_lookups = self._deserialize_currencies(raw_currencies) 1432 1433 return components.CharacterComponent( 1434 activities=activities, 1435 equipment=equipment, 1436 inventory=inventory, 1437 progressions=progressions_, 1438 render_data=render_data, 1439 character=character_, 1440 character_records=character_records, 1441 profile_records=None, 1442 item_components=item_components, 1443 currency_lookups=currency_lookups, 1444 collectibles=collectibles, 1445 nodes=nodes, 1446 ) 1447 1448 def _set_entity_attrs( 1449 self, payload: typedefs.JSONObject, *, key: str = "displayProperties" 1450 ) -> entity.Entity: 1451 name: undefined.UndefinedOr[str] = undefined.UNDEFINED 1452 description: undefined.UndefinedOr[str] = undefined.UNDEFINED 1453 1454 if properties := payload[key]: 1455 if (raw_name := properties["name"]) is not typedefs.Unknown: 1456 name = raw_name 1457 1458 if ( 1459 raw_description := properties["description"] 1460 ) and not typedefs.is_unknown(raw_description): 1461 description = raw_description 1462 1463 return entity.Entity( 1464 net=self._net, 1465 hash=payload["hash"], 1466 index=payload["index"], 1467 name=name, 1468 description=description, 1469 has_icon=properties["hasIcon"], 1470 icon=assets.Image(properties["icon"] if "icon" in properties else None), 1471 ) 1472 1473 def deserialize_inventory_results( 1474 self, payload: typedefs.JSONObject 1475 ) -> iterators.Iterator[entity.SearchableEntity]: 1476 suggested_words: list[str] = payload["suggestedWords"] 1477 1478 def _check_unknown(s: str) -> undefined.UndefinedOr[str]: 1479 return s if not typedefs.is_unknown(s) else undefined.UNDEFINED 1480 1481 return iterators.Iterator( 1482 [ 1483 entity.SearchableEntity( 1484 net=self._net, 1485 hash=data["hash"], 1486 entity_type=data["entityType"], 1487 weight=data["weight"], 1488 suggested_words=suggested_words, 1489 name=data["displayProperties"]["name"], 1490 has_icon=data["displayProperties"]["hasIcon"], 1491 description=_check_unknown( 1492 data["displayProperties"]["description"] 1493 ), 1494 icon=assets.Image(data["displayProperties"]["icon"]), 1495 ) 1496 for data in payload["results"]["results"] 1497 ] 1498 ) 1499 1500 def _deserialize_inventory_item_objects( 1501 self, payload: typedefs.JSONObject 1502 ) -> entity.InventoryEntityObjects: 1503 return entity.InventoryEntityObjects( 1504 action=payload.get("action"), 1505 set_data=payload.get("setData"), 1506 stats=payload.get("stats"), 1507 equipping_block=payload.get("equippingBlock"), 1508 translation_block=payload.get("translationBlock"), 1509 preview=payload.get("preview"), 1510 quality=payload.get("quality"), 1511 value=payload.get("value"), 1512 source_data=payload.get("sourceData"), 1513 objectives=payload.get("objectives"), 1514 plug=payload.get("plug"), 1515 metrics=payload.get("metrics"), 1516 gearset=payload.get("gearset"), 1517 sack=payload.get("sack"), 1518 sockets=payload.get("sockets"), 1519 summary=payload.get("summary"), 1520 talent_gird=payload.get("talentGrid"), 1521 investments_stats=payload.get("investmentStats"), 1522 perks=payload.get("perks"), 1523 animations=payload.get("animations", []), 1524 links=payload.get("links", []), 1525 ) 1526 1527 def deserialize_inventory_entity( # noqa: C901 Too complex. 1528 self, payload: typedefs.JSONObject, / 1529 ) -> entity.InventoryEntity: 1530 props = self._set_entity_attrs(payload) 1531 objects = self._deserialize_inventory_item_objects(payload) 1532 1533 collectible_hash: typing.Optional[int] = None 1534 if raw_collectible_hash := payload.get("collectibleHash"): 1535 collectible_hash = int(raw_collectible_hash) 1536 1537 secondary_icon: undefined.UndefinedOr[assets.Image] = undefined.UNDEFINED 1538 if raw_second_icon := payload.get("secondaryIcon"): 1539 secondary_icon = assets.Image(raw_second_icon) 1540 1541 secondary_overlay: undefined.UndefinedOr[assets.Image] = undefined.UNDEFINED 1542 if raw_second_overlay := payload.get("secondaryOverlay"): 1543 secondary_overlay = assets.Image(raw_second_overlay) 1544 1545 secondary_special: undefined.UndefinedOr[assets.Image] = undefined.UNDEFINED 1546 if raw_second_special := payload.get("secondarySpecial"): 1547 secondary_special = assets.Image(raw_second_special) 1548 1549 screenshot: undefined.UndefinedOr[assets.Image] = undefined.UNDEFINED 1550 if raw_screenshot := payload.get("screenshot"): 1551 screenshot = assets.Image(raw_screenshot) 1552 1553 watermark_icon: typing.Optional[assets.Image] = None 1554 if raw_watermark_icon := payload.get("iconWatermark"): 1555 watermark_icon = assets.Image(raw_watermark_icon) 1556 1557 watermark_shelved: typing.Optional[assets.Image] = None 1558 if raw_watermark_shelved := payload.get("iconWatermarkShelved"): 1559 watermark_shelved = assets.Image(raw_watermark_shelved) 1560 1561 about: undefined.UndefinedOr[str] = undefined.UNDEFINED 1562 if (raw_about := payload.get("flavorText")) and not typedefs.is_unknown( 1563 raw_about 1564 ): 1565 about = raw_about 1566 1567 ui_item_style: undefined.UndefinedOr[str] = undefined.UNDEFINED 1568 if ( 1569 raw_ui_style := payload.get("uiItemDisplayStyle") 1570 ) and not typedefs.is_unknown(raw_ui_style): 1571 ui_item_style = raw_ui_style 1572 1573 tier_and_name: undefined.UndefinedOr[str] = undefined.UNDEFINED 1574 if ( 1575 raw_tier_and_name := payload.get("itemTypeAndTierDisplayName") 1576 ) and not typedefs.is_unknown(raw_tier_and_name): 1577 tier_and_name = raw_tier_and_name 1578 1579 type_name: undefined.UndefinedOr[str] = undefined.UNDEFINED 1580 if ( 1581 raw_type_name := payload.get("itemTypeDisplayName") 1582 ) and not typedefs.is_unknown(raw_type_name): 1583 type_name = raw_type_name 1584 1585 display_source: undefined.UndefinedOr[str] = undefined.UNDEFINED 1586 if ( 1587 raw_display_source := payload.get("displaySource") 1588 ) and not typedefs.is_unknown(raw_display_source): 1589 display_source = raw_display_source 1590 1591 lorehash: typing.Optional[int] = None 1592 if raw_lore_hash := payload.get("loreHash"): 1593 lorehash = int(raw_lore_hash) 1594 1595 summary_hash: typing.Optional[int] = None 1596 if raw_summary_hash := payload.get("summaryItemHash"): 1597 summary_hash = raw_summary_hash 1598 1599 breaker_type_hash: typing.Optional[int] = None 1600 if raw_breaker_type_hash := payload.get("breakerTypeHash"): 1601 breaker_type_hash = int(raw_breaker_type_hash) 1602 1603 damage_types: typing.Optional[collections.Sequence[int]] = None 1604 if raw_damage_types := payload.get("damageTypes"): 1605 damage_types = [int(type_) for type_ in raw_damage_types] 1606 1607 damagetype_hashes: typing.Optional[collections.Sequence[int]] = None 1608 if raw_damagetype_hashes := payload.get("damageTypeHashes"): 1609 damagetype_hashes = [int(type_) for type_ in raw_damagetype_hashes] 1610 1611 default_damagetype_hash: typing.Optional[int] = None 1612 if raw_defaultdmg_hash := payload.get("defaultDamageTypeHash"): 1613 default_damagetype_hash = int(raw_defaultdmg_hash) 1614 1615 emblem_objective_hash: typing.Optional[int] = None 1616 if raw_emblem_obj_hash := payload.get("emblemObjectiveHash"): 1617 emblem_objective_hash = int(raw_emblem_obj_hash) 1618 1619 tier_type: typing.Optional[enums.TierType] = None 1620 tier: typing.Optional[enums.ItemTier] = None 1621 bucket_hash: typing.Optional[int] = None 1622 recovery_hash: typing.Optional[int] = None 1623 tier_name: undefined.UndefinedOr[str] = undefined.UNDEFINED 1624 isinstance_item: bool = False 1625 expire_tool_tip: undefined.UndefinedOr[str] = undefined.UNDEFINED 1626 expire_in_orbit_message: undefined.UndefinedOr[str] = undefined.UNDEFINED 1627 suppress_expiration: bool = False 1628 max_stack_size: typing.Optional[int] = None 1629 stack_label: undefined.UndefinedOr[str] = undefined.UNDEFINED 1630 1631 if inventory := payload.get("inventory"): 1632 tier_type = enums.TierType(int(inventory["tierType"])) 1633 tier = enums.ItemTier(int(inventory["tierTypeHash"])) 1634 bucket_hash = int(inventory["bucketTypeHash"]) 1635 recovery_hash = int(inventory["recoveryBucketTypeHash"]) 1636 tier_name = inventory["tierTypeName"] 1637 isinstance_item = inventory["isInstanceItem"] 1638 suppress_expiration = inventory["suppressExpirationWhenObjectivesComplete"] 1639 max_stack_size = int(inventory["maxStackSize"]) 1640 1641 try: 1642 stack_label = inventory["stackUniqueLabel"] 1643 except KeyError: 1644 pass 1645 1646 return entity.InventoryEntity( 1647 net=self._net, 1648 collectible_hash=collectible_hash, 1649 name=props.name, 1650 about=about, 1651 emblem_objective_hash=emblem_objective_hash, 1652 suppress_expiration=suppress_expiration, 1653 max_stack_size=max_stack_size, 1654 stack_label=stack_label, 1655 tier=tier, 1656 tier_type=tier_type, 1657 tier_name=tier_name, 1658 bucket_hash=bucket_hash, 1659 recovery_bucket_hash=recovery_hash, 1660 isinstance_item=isinstance_item, 1661 expire_in_orbit_message=expire_in_orbit_message, 1662 expiration_tooltip=expire_tool_tip, 1663 lore_hash=lorehash, 1664 type_and_tier_name=tier_and_name, 1665 summary_hash=summary_hash, 1666 ui_display_style=ui_item_style, 1667 type_name=type_name, 1668 breaker_type_hash=breaker_type_hash, 1669 description=props.description, 1670 display_source=display_source, 1671 hash=props.hash, 1672 damage_types=damage_types, 1673 index=props.index, 1674 icon=props.icon, 1675 has_icon=props.has_icon, 1676 screenshot=screenshot, 1677 watermark_icon=watermark_icon, 1678 watermark_shelved=watermark_shelved, 1679 secondary_icon=secondary_icon, 1680 secondary_overlay=secondary_overlay, 1681 secondary_special=secondary_special, 1682 type=enums.ItemType(int(payload["itemType"])), 1683 trait_hashes=[int(id_) for id_ in payload.get("traitHashes", [])], 1684 trait_ids=[trait for trait in payload.get("traitIds", [])], 1685 category_hashes=[int(hash_) for hash_ in payload["itemCategoryHashes"]], 1686 item_class=enums.Class(int(payload["classType"])), 1687 sub_type=enums.ItemSubType(int(payload["itemSubType"])), 1688 breaker_type=int(payload["breakerType"]), 1689 default_damagetype=int(payload["defaultDamageType"]), 1690 default_damagetype_hash=default_damagetype_hash, 1691 damagetype_hashes=damagetype_hashes, 1692 tooltip_notifications=payload["tooltipNotifications"], 1693 not_transferable=payload["nonTransferrable"], 1694 allow_actions=payload["allowActions"], 1695 is_equippable=payload["equippable"], 1696 objects=objects, 1697 background_colors=payload.get("backgroundColor", {}), 1698 season_hash=payload.get("seasonHash"), 1699 has_postmaster_effect=payload["doesPostmasterPullHaveSideEffects"], 1700 ) 1701 1702 def deserialize_objective_entity( 1703 self, payload: typedefs.JSONObject, / 1704 ) -> entity.ObjectiveEntity: 1705 props = self._set_entity_attrs(payload) 1706 return entity.ObjectiveEntity( 1707 net=self._net, 1708 hash=props.hash, 1709 index=props.index, 1710 description=props.description, 1711 name=props.name, 1712 has_icon=props.has_icon, 1713 icon=props.icon, 1714 unlock_value_hash=payload["unlockValueHash"], 1715 completion_value=payload["completionValue"], 1716 scope=entity.GatingScope(int(payload["scope"])), 1717 location_hash=payload["locationHash"], 1718 allowed_negative_value=payload["allowNegativeValue"], 1719 allowed_value_change=payload["allowValueChangeWhenCompleted"], 1720 counting_downward=payload["isCountingDownward"], 1721 value_style=entity.ValueUIStyle(int(payload["valueStyle"])), 1722 progress_description=payload["progressDescription"], 1723 perks=payload["perks"], 1724 stats=payload["stats"], 1725 minimum_visibility=payload["minimumVisibilityThreshold"], 1726 allow_over_completion=payload["allowOvercompletion"], 1727 show_value_style=payload["showValueOnComplete"], 1728 display_only_objective=payload["isDisplayOnlyObjective"], 1729 complete_value_style=entity.ValueUIStyle( 1730 int(payload["completedValueStyle"]) 1731 ), 1732 progress_value_style=entity.ValueUIStyle( 1733 int(payload["inProgressValueStyle"]) 1734 ), 1735 ui_label=payload["uiLabel"], 1736 ui_style=entity.ObjectiveUIStyle(int(payload["uiStyle"])), 1737 ) 1738 1739 def _deserialize_activity_values( 1740 self, payload: typedefs.JSONObject, / 1741 ) -> activity.ActivityValues: 1742 team: typing.Optional[int] = None 1743 if raw_team := payload.get("team"): 1744 team = raw_team["basic"]["value"] 1745 return activity.ActivityValues( 1746 assists=payload["assists"]["basic"]["value"], 1747 deaths=payload["deaths"]["basic"]["value"], 1748 kills=payload["kills"]["basic"]["value"], 1749 is_completed=bool(payload["completed"]["basic"]["value"]), 1750 opponents_defeated=payload["opponentsDefeated"]["basic"]["value"], 1751 efficiency=payload["efficiency"]["basic"]["value"], 1752 kd_ratio=payload["killsDeathsRatio"]["basic"]["value"], 1753 kd_assists=payload["killsDeathsAssists"]["basic"]["value"], 1754 score=payload["score"]["basic"]["value"], 1755 duration=payload["activityDurationSeconds"]["basic"]["displayValue"], 1756 team=team, 1757 completion_reason=payload["completionReason"]["basic"]["displayValue"], 1758 fireteam_id=payload["fireteamId"]["basic"]["value"], 1759 start_seconds=payload["startSeconds"]["basic"]["value"], 1760 played_time=payload["timePlayedSeconds"]["basic"]["displayValue"], 1761 player_count=payload["playerCount"]["basic"]["value"], 1762 team_score=payload["teamScore"]["basic"]["value"], 1763 ) 1764 1765 def deserialize_activity( 1766 self, 1767 payload: typedefs.JSONObject, 1768 /, 1769 ) -> activity.Activity: 1770 period = time.clean_date(payload["period"]) 1771 details = payload["activityDetails"] 1772 ref_id = int(details["referenceId"]) 1773 instance_id = int(details["instanceId"]) 1774 mode = enums.GameMode(details["mode"]) 1775 modes = [enums.GameMode(int(mode_)) for mode_ in details["modes"]] 1776 is_private = details["isPrivate"] 1777 membership_type = enums.MembershipType(int(details["membershipType"])) 1778 1779 # Since we're using the same fields for post activity method 1780 # this check is required since post activity doesn't values values 1781 values = self._deserialize_activity_values(payload["values"]) 1782 1783 return activity.Activity( 1784 net=self._net, 1785 hash=ref_id, 1786 instance_id=instance_id, 1787 mode=mode, 1788 modes=modes, 1789 is_private=is_private, 1790 membership_type=membership_type, 1791 occurred_at=period, 1792 values=values, 1793 ) 1794 1795 def deserialize_activities( 1796 self, payload: typedefs.JSONObject 1797 ) -> iterators.Iterator[activity.Activity]: 1798 return iterators.Iterator( 1799 [ 1800 self.deserialize_activity(activity_) 1801 for activity_ in payload["activities"] 1802 ] 1803 ) 1804 1805 def deserialize_extended_weapon_values( 1806 self, payload: typedefs.JSONObject 1807 ) -> activity.ExtendedWeaponValues: 1808 assists: typing.Optional[int] = None 1809 if raw_assists := payload["values"].get("uniqueWeaponAssists"): 1810 assists = raw_assists["basic"]["value"] 1811 assists_damage: typing.Optional[int] = None 1812 1813 if raw_assists_damage := payload["values"].get("uniqueWeaponAssistDamage"): 1814 assists_damage = raw_assists_damage["basic"]["value"] 1815 1816 return activity.ExtendedWeaponValues( 1817 reference_id=int(payload["referenceId"]), 1818 kills=payload["values"]["uniqueWeaponKills"]["basic"]["value"], 1819 precision_kills=payload["values"]["uniqueWeaponPrecisionKills"]["basic"][ 1820 "value" 1821 ], 1822 assists=assists, 1823 assists_damage=assists_damage, 1824 precision_kills_percentage=( 1825 payload["values"]["uniqueWeaponKillsPrecisionKills"]["basic"]["value"], 1826 payload["values"]["uniqueWeaponKillsPrecisionKills"]["basic"][ 1827 "displayValue" 1828 ], 1829 ), 1830 ) 1831 1832 def _deserialize_extended_values( 1833 self, payload: typedefs.JSONObject 1834 ) -> activity.ExtendedValues: 1835 weapons: typing.Optional[ 1836 collections.Collection[activity.ExtendedWeaponValues] 1837 ] = None 1838 1839 if raw_weapons := payload.get("weapons"): 1840 weapons = [ 1841 self.deserialize_extended_weapon_values(value) for value in raw_weapons 1842 ] 1843 1844 return activity.ExtendedValues( 1845 precision_kills=payload["values"]["precisionKills"]["basic"]["value"], 1846 grenade_kills=payload["values"]["weaponKillsGrenade"]["basic"]["value"], 1847 melee_kills=payload["values"]["weaponKillsMelee"]["basic"]["value"], 1848 super_kills=payload["values"]["weaponKillsSuper"]["basic"]["value"], 1849 ability_kills=payload["values"]["weaponKillsAbility"]["basic"]["value"], 1850 weapons=weapons, 1851 ) 1852 1853 def deserialize_post_activity_player( 1854 self, payload: typedefs.JSONObject, / 1855 ) -> activity.PostActivityPlayer: 1856 player = payload["player"] 1857 1858 class_hash: typedefs.NoneOr[int] = None 1859 if (class_hash := player.get("classHash")) is not None: 1860 class_hash = class_hash 1861 1862 race_hash: typedefs.NoneOr[int] = None 1863 if (race_hash := player.get("raceHash")) is not None: 1864 race_hash = race_hash 1865 1866 gender_hash: typedefs.NoneOr[int] = None 1867 if (gender_hash := player.get("genderHash")) is not None: 1868 gender_hash = gender_hash 1869 1870 character_class: undefined.UndefinedOr[str] = undefined.UNDEFINED 1871 if ( 1872 character_class := player.get("characterClass") 1873 ) and not typedefs.is_unknown(character_class): 1874 character_class = character_class 1875 1876 character_level: typedefs.NoneOr[int] = None 1877 if (character_level := player.get("characterLevel")) is not None: 1878 character_level = character_level 1879 1880 return activity.PostActivityPlayer( 1881 standing=int(payload["standing"]), 1882 score=int(payload["score"]["basic"]["value"]), 1883 character_id=payload["characterId"], 1884 destiny_user=self.deserialize_destiny_membership(player["destinyUserInfo"]), 1885 character_class=character_class, 1886 character_level=character_level, 1887 race_hash=race_hash, 1888 gender_hash=gender_hash, 1889 class_hash=class_hash, 1890 light_level=int(player["lightLevel"]), 1891 emblem_hash=int(player["emblemHash"]), 1892 values=self._deserialize_activity_values(payload["values"]), 1893 extended_values=self._deserialize_extended_values(payload["extended"]), 1894 ) 1895 1896 def _deserialize_post_activity_team( 1897 self, payload: typedefs.JSONObject 1898 ) -> activity.PostActivityTeam: 1899 return activity.PostActivityTeam( 1900 id=payload["teamId"], 1901 is_defeated=bool(payload["standing"]["basic"]["value"]), 1902 score=int(payload["score"]["basic"]["value"]), 1903 name=payload["teamName"], 1904 ) 1905 1906 def deserialize_post_activity( 1907 self, payload: typedefs.JSONObject 1908 ) -> activity.PostActivity: 1909 period = time.clean_date(payload["period"]) 1910 details = payload["activityDetails"] 1911 ref_id = int(details["referenceId"]) 1912 instance_id = int(details["instanceId"]) 1913 mode = enums.GameMode(details["mode"]) 1914 modes = [enums.GameMode(int(mode_)) for mode_ in details["modes"]] 1915 is_private = details["isPrivate"] 1916 membership_type = enums.MembershipType(int(details["membershipType"])) 1917 return activity.PostActivity( 1918 net=self._net, 1919 hash=ref_id, 1920 membership_type=membership_type, 1921 instance_id=instance_id, 1922 mode=mode, 1923 modes=modes, 1924 is_private=is_private, 1925 occurred_at=period, 1926 starting_phase=int(payload["startingPhaseIndex"]), 1927 players=[ 1928 self.deserialize_post_activity_player(player) 1929 for player in payload["entries"] 1930 ], 1931 teams=[ 1932 self._deserialize_post_activity_team(team) for team in payload["teams"] 1933 ], 1934 ) 1935 1936 def _deserialize_aggregated_activity_values( 1937 self, payload: typedefs.JSONObject 1938 ) -> activity.AggregatedActivityValues: 1939 # This ID is always the same for all aggregated values. 1940 activity_id = int(payload["fastestCompletionMsForActivity"]["activityId"]) 1941 1942 return activity.AggregatedActivityValues( 1943 id=activity_id, 1944 fastest_completion_time=( 1945 int(payload["fastestCompletionMsForActivity"]["basic"]["value"]), 1946 payload["fastestCompletionMsForActivity"]["basic"]["displayValue"], 1947 ), 1948 completions=int(payload["activityCompletions"]["basic"]["value"]), 1949 kills=int(payload["activityKills"]["basic"]["value"]), 1950 deaths=int(payload["activityDeaths"]["basic"]["value"]), 1951 assists=int(payload["activityAssists"]["basic"]["value"]), 1952 seconds_played=( 1953 int(payload["activitySecondsPlayed"]["basic"]["value"]), 1954 payload["activitySecondsPlayed"]["basic"]["displayValue"], 1955 ), 1956 wins=int(payload["activityWins"]["basic"]["value"]), 1957 goals_missed=int(payload["activityGoalsMissed"]["basic"]["value"]), 1958 special_actions=int(payload["activitySpecialActions"]["basic"]["value"]), 1959 best_goals_hit=int(payload["activityBestGoalsHit"]["basic"]["value"]), 1960 best_single_score=int( 1961 payload["activityBestSingleGameScore"]["basic"]["value"] 1962 ), 1963 goals_hit=int(payload["activityGoalsHit"]["basic"]["value"]), 1964 special_score=int(payload["activitySpecialScore"]["basic"]["value"]), 1965 kd_assists=int(payload["activityKillsDeathsAssists"]["basic"]["value"]), 1966 kd_ratio=float( 1967 payload["activityKillsDeathsAssists"]["basic"]["displayValue"] 1968 ), 1969 precision_kills=int(payload["activityPrecisionKills"]["basic"]["value"]), 1970 ) 1971 1972 def deserialize_aggregated_activity( 1973 self, payload: typedefs.JSONObject 1974 ) -> activity.AggregatedActivity: 1975 return activity.AggregatedActivity( 1976 hash=int(payload["activityHash"]), 1977 values=self._deserialize_aggregated_activity_values(payload["values"]), 1978 ) 1979 1980 def deserialize_aggregated_activities( 1981 self, payload: typedefs.JSONObject 1982 ) -> iterators.Iterator[activity.AggregatedActivity]: 1983 return iterators.Iterator( 1984 [ 1985 self.deserialize_aggregated_activity(activity) 1986 for activity in payload["activities"] 1987 ] 1988 ) 1989 1990 def deserialize_linked_profiles( 1991 self, payload: typedefs.JSONObject 1992 ) -> profile.LinkedProfile: 1993 bungie_user = self.deserialize_partial_bungie_user(payload["bnetMembership"]) 1994 error_profiles_vec: typing.MutableSequence[user.DestinyMembership] = [] 1995 profiles_vec: typing.MutableSequence[user.DestinyMembership] = [] 1996 1997 if raw_profile := payload.get("profiles"): 1998 for pfile in raw_profile: 1999 profiles_vec.append(self.deserialize_destiny_membership(pfile)) 2000 2001 if raw_profiles_with_errors := payload.get("profilesWithErrors"): 2002 for raw_error_pfile in raw_profiles_with_errors: 2003 if error_pfile := raw_error_pfile.get("infoCard"): 2004 error_profiles_vec.append( 2005 self.deserialize_destiny_membership(error_pfile) 2006 ) 2007 2008 return profile.LinkedProfile( 2009 net=self._net, 2010 bungie=bungie_user, 2011 profiles=profiles_vec, 2012 profiles_with_errors=error_profiles_vec, 2013 ) 2014 2015 def deserialize_clan_banners( 2016 self, payload: typedefs.JSONObject 2017 ) -> collections.Sequence[clans.ClanBanner]: 2018 banners_seq: typing.MutableSequence[clans.ClanBanner] = [] 2019 if banners := payload.get("clanBannerDecals"): 2020 for k, v in banners.items(): 2021 banner_obj = clans.ClanBanner( 2022 id=int(k), 2023 foreground=assets.Image(v["foregroundPath"]), 2024 background=assets.Image(v["backgroundPath"]), 2025 ) 2026 banners_seq.append(banner_obj) 2027 return banners_seq 2028 2029 def deserialize_public_milestone_content( 2030 self, payload: typedefs.JSONObject 2031 ) -> milestones.MilestoneContent: 2032 items_categoris: typedefs.NoneOr[milestones.MilestoneItems] = None 2033 if raw_categories := payload.get("itemCategories"): 2034 for item in raw_categories: 2035 title = undefined.UNDEFINED 2036 if raw_title := item.get("title"): 2037 if raw_title != typedefs.Unknown: 2038 title = raw_title 2039 if raw_hashes := item.get("itemHashes"): 2040 hashes: collections.Sequence[int] = raw_hashes 2041 2042 items_categoris = milestones.MilestoneItems(title=title, hashes=hashes) 2043 2044 about = undefined.UNDEFINED 2045 if (raw_about := payload["about"]) != typedefs.Unknown: 2046 about = raw_about 2047 2048 status = undefined.UNDEFINED 2049 if (raw_status := payload["status"]) != typedefs.Unknown: 2050 status = raw_status 2051 2052 tips: typing.MutableSequence[undefined.UndefinedOr[str]] = [] 2053 if raw_tips := payload.get("tips"): 2054 for raw_tip in raw_tips: 2055 if raw_tip == typedefs.Unknown: 2056 raw_tip = undefined.UNDEFINED 2057 tips.append(raw_tip) 2058 2059 return milestones.MilestoneContent( 2060 about=about, status=status, tips=tips, items=items_categoris 2061 ) 2062 2063 def deserialize_friend(self, payload: typedefs.JSONObject, /) -> friends.Friend: 2064 name = undefined.UNDEFINED 2065 if (raw_name := payload["bungieGlobalDisplayName"]) != typedefs.Unknown: 2066 name = raw_name 2067 2068 bungie_user: typedefs.NoneOr[user.BungieUser] = None 2069 2070 if raw_bungie_user := payload.get("bungieNetUser"): 2071 bungie_user = self.deserialize_bungie_user(raw_bungie_user) 2072 2073 return friends.Friend( 2074 net=self._net, 2075 id=int(payload["lastSeenAsMembershipId"]), 2076 name=name, 2077 code=payload.get("bungieGlobalDisplayNameCode"), 2078 relationship=enums.Relationship(payload["relationship"]), 2079 user=bungie_user, 2080 online_status=enums.Presence(payload["onlineStatus"]), 2081 online_title=payload["onlineTitle"], 2082 type=enums.MembershipType(payload["lastSeenAsBungieMembershipType"]), 2083 ) 2084 2085 def deserialize_friends( 2086 self, payload: typedefs.JSONObject 2087 ) -> collections.Sequence[friends.Friend]: 2088 mut_seq: typing.MutableSequence[friends.Friend] = [] 2089 if raw_friends := payload.get("friends"): 2090 for friend in raw_friends: 2091 mut_seq.append(self.deserialize_friend(friend)) 2092 return mut_seq 2093 2094 def deserialize_friend_requests( 2095 self, payload: typedefs.JSONObject 2096 ) -> friends.FriendRequestView: 2097 incoming: typing.MutableSequence[friends.Friend] = [] 2098 outgoing: typing.MutableSequence[friends.Friend] = [] 2099 2100 if raw_incoming_requests := payload.get("incomingRequests"): 2101 for incoming_request in raw_incoming_requests: 2102 incoming.append(self.deserialize_friend(incoming_request)) 2103 2104 if raw_outgoing_requests := payload.get("outgoingRequests"): 2105 for outgoing_request in raw_outgoing_requests: 2106 outgoing.append(self.deserialize_friend(outgoing_request)) 2107 2108 return friends.FriendRequestView(incoming=incoming, outgoing=outgoing) 2109 2110 def _set_fireteam_fields( 2111 self, payload: typedefs.JSONObject, total_results: typing.Optional[int] = None 2112 ) -> fireteams.Fireteam: 2113 activity_type = fireteams.FireteamActivity(payload["activityType"]) 2114 return fireteams.Fireteam( 2115 id=int(payload["fireteamId"]), 2116 group_id=int(payload["groupId"]), 2117 platform=fireteams.FireteamPlatform(payload["platform"]), 2118 is_immediate=payload["isImmediate"], 2119 activity_type=activity_type, 2120 owner_id=int(payload["ownerMembershipId"]), 2121 player_slot_count=payload["playerSlotCount"], 2122 available_player_slots=payload["availablePlayerSlotCount"], 2123 available_alternate_slots=payload["availableAlternateSlotCount"], 2124 title=payload["title"], 2125 date_created=time.clean_date(payload["dateCreated"]), 2126 is_public=payload["isPublic"], 2127 locale=fireteams.FireteamLanguage(payload["locale"]), 2128 is_valid=payload["isValid"], 2129 last_modified=time.clean_date(payload["datePlayerModified"]), 2130 total_results=total_results or 0, 2131 ) 2132 2133 def deserialize_fireteams( 2134 self, payload: typedefs.JSONObject 2135 ) -> typedefs.NoneOr[collections.Sequence[fireteams.Fireteam]]: 2136 fireteams_: typing.MutableSequence[fireteams.Fireteam] = [] 2137 2138 result: list[typedefs.JSONObject] 2139 if not (result := payload["results"]): 2140 return None 2141 for elem in result: 2142 fireteams_.append( 2143 self._set_fireteam_fields( 2144 elem, total_results=int(payload["totalResults"]) 2145 ) 2146 ) 2147 return fireteams_ 2148 2149 def deserialize_fireteam_destiny_users( 2150 self, payload: typedefs.JSONObject 2151 ) -> fireteams.FireteamUser: 2152 destiny_obj = self.deserialize_destiny_membership(payload) 2153 # We could helpers.just return a DestinyMembership object but this is 2154 # missing the fireteam display name and id fields. 2155 return fireteams.FireteamUser( 2156 net=self._net, 2157 id=destiny_obj.id, 2158 code=destiny_obj.code, 2159 icon=destiny_obj.icon, 2160 types=destiny_obj.types, 2161 type=destiny_obj.type, 2162 is_public=destiny_obj.is_public, 2163 crossave_override=destiny_obj.crossave_override, 2164 name=destiny_obj.name, 2165 last_seen_name=destiny_obj.last_seen_name, 2166 fireteam_display_name=payload["FireteamDisplayName"], 2167 fireteam_membership_id=enums.MembershipType( 2168 payload["FireteamMembershipType"] 2169 ), 2170 ) 2171 2172 def deserialize_fireteam_members( 2173 self, payload: typedefs.JSONObject, *, alternatives: bool = False 2174 ) -> collections.Sequence[fireteams.FireteamMember]: 2175 members_: list[fireteams.FireteamMember] = [] 2176 if members := payload.get("Members" if not alternatives else "Alternates"): 2177 for member in members: 2178 bungie_fields = self.deserialize_partial_bungie_user(member) 2179 members_fields = fireteams.FireteamMember( 2180 destiny_user=self.deserialize_fireteam_destiny_users(member), 2181 has_microphone=member["hasMicrophone"], 2182 character_id=int(member["characterId"]), 2183 date_joined=time.clean_date(member["dateJoined"]), 2184 last_platform_invite_date=time.clean_date( 2185 member["lastPlatformInviteAttemptDate"] 2186 ), 2187 last_platform_invite_result=int( 2188 member["lastPlatformInviteAttemptResult"] 2189 ), 2190 net=self._net, 2191 name=bungie_fields.name, 2192 id=bungie_fields.id, 2193 icon=bungie_fields.icon, 2194 is_public=bungie_fields.is_public, 2195 crossave_override=bungie_fields.crossave_override, 2196 types=bungie_fields.types, 2197 type=bungie_fields.type, 2198 ) 2199 members_.append(members_fields) 2200 return members_ 2201 2202 def deserialize_available_fireteams( 2203 self, 2204 data: typedefs.JSONObject, 2205 *, 2206 no_results: bool = False, 2207 ) -> typing.Union[ 2208 fireteams.AvailableFireteam, collections.Sequence[fireteams.AvailableFireteam] 2209 ]: 2210 fireteams_: list[fireteams.AvailableFireteam] = [] 2211 2212 # This needs to be used outside the results 2213 # JSON key. 2214 if no_results: 2215 payload = data.copy() 2216 2217 if (results := payload.get("results")) is not None: 2218 for fireteam in results: 2219 found_fireteams = self._set_fireteam_fields(fireteam["Summary"]) 2220 fireteams_fields = fireteams.AvailableFireteam( 2221 id=found_fireteams.id, 2222 group_id=found_fireteams.group_id, 2223 platform=found_fireteams.platform, 2224 activity_type=found_fireteams.activity_type, 2225 is_immediate=found_fireteams.is_immediate, 2226 is_public=found_fireteams.is_public, 2227 is_valid=found_fireteams.is_valid, 2228 owner_id=found_fireteams.owner_id, 2229 player_slot_count=found_fireteams.player_slot_count, 2230 available_player_slots=found_fireteams.available_player_slots, 2231 available_alternate_slots=found_fireteams.available_alternate_slots, 2232 title=found_fireteams.title, 2233 date_created=found_fireteams.date_created, 2234 locale=found_fireteams.locale, 2235 last_modified=found_fireteams.last_modified, 2236 total_results=found_fireteams.total_results, 2237 members=self.deserialize_fireteam_members(payload), 2238 alternatives=self.deserialize_fireteam_members( 2239 payload, alternatives=True 2240 ), 2241 ) 2242 if no_results: 2243 return fireteams_fields 2244 else: 2245 fireteams_.append(fireteams_fields) 2246 return fireteams_ 2247 2248 def deserialize_fireteam_party( 2249 self, payload: typedefs.JSONObject 2250 ) -> fireteams.FireteamParty: 2251 last_destination_hash: typing.Optional[int] = None 2252 if raw_dest_hash := payload.get("lastOrbitedDestinationHash"): 2253 last_destination_hash = int(raw_dest_hash) 2254 2255 return fireteams.FireteamParty( 2256 members=[ 2257 self._deserialize_fireteam_party_member(member) 2258 for member in payload["partyMembers"] 2259 ], 2260 activity=self._deserialize_fireteam_party_current_activity( 2261 payload["currentActivity"] 2262 ), 2263 settings=self._deserialize_fireteam_party_settings(payload["joinability"]), 2264 last_destination_hash=last_destination_hash, 2265 tracking=payload["tracking"], 2266 ) 2267 2268 def _deserialize_fireteam_party_member( 2269 self, payload: typedefs.JSONObject 2270 ) -> fireteams.FireteamPartyMember: 2271 status = fireteams.FireteamPartyMemberState(payload["status"]) 2272 displayname: undefined.UndefinedOr[str] = undefined.UNDEFINED 2273 if raw_name := payload.get("displayName"): 2274 displayname = raw_name 2275 2276 return fireteams.FireteamPartyMember( 2277 membership_id=int(payload["membershipId"]), 2278 emblem_hash=int(payload["emblemHash"]), 2279 status=status, 2280 display_name=displayname, 2281 ) 2282 2283 def _deserialize_fireteam_party_current_activity( 2284 self, payload: typedefs.JSONObject 2285 ) -> fireteams.FireteamPartyCurrentActivity: 2286 start_date: typing.Optional[datetime.datetime] = None 2287 if raw_start_date := payload.get("startTime"): 2288 start_date = time.clean_date(raw_start_date) 2289 2290 end_date: typing.Optional[datetime.datetime] = None 2291 if raw_end_date := payload.get("endTime"): 2292 end_date = time.clean_date(raw_end_date) 2293 return fireteams.FireteamPartyCurrentActivity( 2294 start_time=start_date, 2295 end_time=end_date, 2296 score=float(payload["score"]), 2297 highest_opposing_score=float(payload["highestOpposingFactionScore"]), 2298 opponenst_count=int(payload["numberOfOpponents"]), 2299 player_count=int(payload["numberOfPlayers"]), 2300 ) 2301 2302 def _deserialize_fireteam_party_settings( 2303 self, payload: typedefs.JSONObject 2304 ) -> fireteams.FireteamPartySettings: 2305 closed_reasons = enums.ClosedReasons(payload["closedReasons"]) 2306 return fireteams.FireteamPartySettings( 2307 open_slots=int(payload["openSlots"]), 2308 privacy_setting=enums.PrivacySetting(int(payload["privacySetting"])), 2309 closed_reasons=closed_reasons, 2310 ) 2311 2312 def deserialize_seasonal_artifact( 2313 self, payload: typedefs.JSONObject 2314 ) -> season.Artifact: 2315 if raw_artifact := payload.get("seasonalArtifact"): 2316 if points := raw_artifact.get("pointProgression"): 2317 points_prog = progressions.Progression( 2318 hash=points["progressionHash"], 2319 level=points["level"], 2320 cap=points["levelCap"], 2321 daily_limit=points["dailyLimit"], 2322 weekly_limit=points["weeklyLimit"], 2323 current_progress=points["currentProgress"], 2324 daily_progress=points["dailyProgress"], 2325 needed=points["progressToNextLevel"], 2326 next_level=points["nextLevelAt"], 2327 ) 2328 2329 if bonus := raw_artifact.get("powerBonusProgression"): 2330 power_bonus_prog = progressions.Progression( 2331 hash=bonus["progressionHash"], 2332 level=bonus["level"], 2333 cap=bonus["levelCap"], 2334 daily_limit=bonus["dailyLimit"], 2335 weekly_limit=bonus["weeklyLimit"], 2336 current_progress=bonus["currentProgress"], 2337 daily_progress=bonus["dailyProgress"], 2338 needed=bonus["progressToNextLevel"], 2339 next_level=bonus["nextLevelAt"], 2340 ) 2341 artifact = season.Artifact( 2342 net=self._net, 2343 hash=raw_artifact["artifactHash"], 2344 power_bonus=raw_artifact["powerBonus"], 2345 acquired_points=raw_artifact["pointsAcquired"], 2346 bonus=power_bonus_prog, 2347 points=points_prog, 2348 ) 2349 return artifact 2350 2351 def deserialize_profile_progression( 2352 self, payload: typedefs.JSONObject 2353 ) -> profile.ProfileProgression: 2354 return profile.ProfileProgression( 2355 artifact=self.deserialize_seasonal_artifact(payload["data"]), 2356 checklist={ 2357 int(check_id): checklists 2358 for check_id, checklists in payload["data"]["checklists"].items() 2359 }, 2360 ) 2361 2362 def deserialize_instanced_item( 2363 self, payload: typedefs.JSONObject 2364 ) -> items.ItemInstance: 2365 damage_type_hash: typing.Optional[int] = None 2366 if raw_damagetype_hash := payload.get("damageTypeHash"): 2367 damage_type_hash = int(raw_damagetype_hash) 2368 2369 required_hashes: typing.Optional[collections.Collection[int]] = None 2370 if raw_required_hashes := payload.get("unlockHashesRequiredToEquip"): 2371 required_hashes = [int(raw_hash) for raw_hash in raw_required_hashes] 2372 2373 breaker_type: typing.Optional[items.ItemBreakerType] = None 2374 if raw_break_type := payload.get("breakerType"): 2375 breaker_type = items.ItemBreakerType(int(raw_break_type)) 2376 2377 breaker_type_hash: typing.Optional[int] = None 2378 if raw_break_type_hash := payload.get("breakerTypeHash"): 2379 breaker_type_hash = int(raw_break_type_hash) 2380 2381 energy: typing.Optional[items.ItemEnergy] = None 2382 if raw_energy := payload.get("energy"): 2383 energy = self.deserialize_item_energy(raw_energy) 2384 2385 primary_stats = None 2386 if raw_primary_stats := payload.get("primaryStat"): 2387 primary_stats = self.deserialize_item_stats_view(raw_primary_stats) 2388 2389 return items.ItemInstance( 2390 damage_type=enums.DamageType(int(payload["damageType"])), 2391 damage_type_hash=damage_type_hash, 2392 primary_stat=primary_stats, 2393 item_level=int(payload["itemLevel"]), 2394 quality=int(payload["quality"]), 2395 is_equipped=payload["isEquipped"], 2396 can_equip=payload["canEquip"], 2397 equip_required_level=int(payload["equipRequiredLevel"]), 2398 required_equip_unlock_hashes=required_hashes, 2399 cant_equip_reason=int(payload["cannotEquipReason"]), 2400 breaker_type=breaker_type, 2401 breaker_type_hash=breaker_type_hash, 2402 energy=energy, 2403 ) 2404 2405 def deserialize_item_energy(self, payload: typedefs.JSONObject) -> items.ItemEnergy: 2406 energy_hash: typing.Optional[int] = None 2407 if raw_energy_hash := payload.get("energyTypeHash"): 2408 energy_hash = int(raw_energy_hash) 2409 2410 return items.ItemEnergy( 2411 hash=energy_hash, 2412 type=items.ItemEnergyType(int(payload["energyType"])), 2413 capacity=int(payload["energyCapacity"]), 2414 used_energy=int(payload["energyUsed"]), 2415 unused_energy=int(payload["energyUnused"]), 2416 ) 2417 2418 def deserialize_item_perk(self, payload: typedefs.JSONObject) -> items.ItemPerk: 2419 perk_hash: typing.Optional[int] = None 2420 if raw_perk_hash := payload.get("perkHash"): 2421 perk_hash = int(raw_perk_hash) 2422 2423 return items.ItemPerk( 2424 hash=perk_hash, 2425 icon=assets.Image(payload["iconPath"]), 2426 is_active=payload["isActive"], 2427 is_visible=payload["visible"], 2428 ) 2429 2430 def deserialize_item_socket(self, payload: typedefs.JSONObject) -> items.ItemSocket: 2431 plug_hash: typing.Optional[int] = None 2432 if raw_plug_hash := payload.get("plugHash"): 2433 plug_hash = int(raw_plug_hash) 2434 2435 enable_fail_indexes: typing.Optional[list[int]] = None 2436 if raw_indexes := payload.get("enableFailIndexes"): 2437 enable_fail_indexes = [int(index) for index in raw_indexes] 2438 2439 return items.ItemSocket( 2440 plug_hash=plug_hash, 2441 is_enabled=payload["isEnabled"], 2442 enable_fail_indexes=enable_fail_indexes, 2443 is_visible=payload.get("visible"), 2444 ) 2445 2446 def deserialize_item_stats_view( 2447 self, payload: typedefs.JSONObject 2448 ) -> items.ItemStatsView: 2449 return items.ItemStatsView( 2450 stat_hash=payload.get("statHash"), value=payload.get("value") 2451 ) 2452 2453 def deserialize_plug_item_state( 2454 self, payload: typedefs.JSONObject 2455 ) -> items.PlugItemState: 2456 item_hash: typing.Optional[int] = None 2457 if raw_item_hash := payload.get("plugItemHash"): 2458 item_hash = int(raw_item_hash) 2459 2460 insert_fail_indexes: typedefs.NoneOr[list[int]] = None 2461 if raw_fail_indexes := payload.get("insertFailIndexes"): 2462 insert_fail_indexes = [int(k) for k in raw_fail_indexes] 2463 2464 enable_fail_indexes: typedefs.NoneOr[list[int]] = None 2465 if raw_enabled_indexes := payload.get("enableFailIndexes"): 2466 enable_fail_indexes = [int(k) for k in raw_enabled_indexes] 2467 2468 return items.PlugItemState( 2469 item_hash=item_hash, 2470 insert_fail_indexes=insert_fail_indexes, 2471 enable_fail_indexes=enable_fail_indexes, 2472 is_enabled=payload["enabled"], 2473 can_insert=payload["canInsert"], 2474 )
The base deserialization factory class for all aiobungie objects.
This entity factory is used to deserialize JSON responses from the REST client and turning them
into a aiobungie.crates Python classes.
73 def deserialize_bungie_user(self, data: typedefs.JSONObject) -> user.BungieUser: 74 return user.BungieUser( 75 id=int(data["membershipId"]), 76 created_at=time.clean_date(data["firstAccess"]), 77 name=data.get("cachedBungieGlobalDisplayName", undefined.UNDEFINED), 78 is_deleted=data["isDeleted"], 79 about=data["about"], 80 updated_at=time.clean_date(data["lastUpdate"]), 81 psn_name=data.get("psnDisplayName", None), 82 stadia_name=data.get("stadiaDisplayName", None), 83 steam_name=data.get("steamDisplayName", None), 84 twitch_name=data.get("twitchDisplayName", None), 85 blizzard_name=data.get("blizzardDisplayName", None), 86 status=data["statusText"], 87 locale=data["locale"], 88 picture=assets.Image(path=str(data["profilePicturePath"])), 89 code=data.get("cachedBungieGlobalDisplayNameCode", None), 90 unique_name=data.get("uniqueName", None), 91 theme_id=int(data["profileTheme"]), 92 show_activity=bool(data["showActivity"]), 93 theme_name=data["profileThemeName"], 94 display_title=data["userTitleDisplay"], 95 )
Deserialize a raw JSON Bungie.net user only payload into a user object.
This only returns the Bungie.net user and not the Destiny memberships.
Parameters
- data (
aiobungie.typedefs.JSONObject): The JSON data/payload.
Returns
aiobungie.crates.BungieUser: A Bungie user.
97 def deserialize_partial_bungie_user( 98 self, payload: typedefs.JSONObject 99 ) -> user.PartialBungieUser: 100 return user.PartialBungieUser( 101 net=self._net, 102 types=[ 103 enums.MembershipType(type_) 104 for type_ in payload.get("applicableMembershipTypes", []) 105 ], 106 name=payload.get("displayName", undefined.UNDEFINED), 107 id=int(payload["membershipId"]), 108 crossave_override=enums.MembershipType(payload["crossSaveOverride"]), 109 is_public=payload["isPublic"], 110 icon=assets.Image(payload.get("iconPath", "")), 111 type=enums.MembershipType(payload["membershipType"]), 112 )
Deserialize a raw JSON of a partial bungieNetUserInfo.
A partial user is a bungie.net user payload with missing information from
the main BungieUser object.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.PartialBungieUser: A partial bungie user.
114 def deserialize_destiny_membership( 115 self, payload: typedefs.JSONObject 116 ) -> user.DestinyMembership: 117 name: undefined.UndefinedOr[str] = undefined.UNDEFINED 118 if ( 119 raw_name := payload.get("bungieGlobalDisplayName", "") 120 ) and not typedefs.is_unknown(raw_name): 121 name = raw_name 122 123 return user.DestinyMembership( 124 net=self._net, 125 id=int(payload["membershipId"]), 126 name=name, 127 code=payload.get("bungieGlobalDisplayNameCode", None), 128 last_seen_name=payload.get("LastSeenDisplayName") 129 or payload.get("displayName") # noqa: W503 130 or "", # noqa: W503 131 type=enums.MembershipType(payload["membershipType"]), 132 is_public=payload["isPublic"], 133 crossave_override=enums.MembershipType(payload["crossSaveOverride"]), 134 icon=assets.Image(payload.get("iconPath", "")), 135 types=[ 136 enums.MembershipType(type_) 137 for type_ in payload.get("applicableMembershipTypes", []) 138 ], 139 )
Deserialize a raw JSON of destinyUserInfo destiny membership information.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.user.DestinyMembership: A Destiny 2 membership.
141 def deserialize_destiny_memberships( 142 self, data: typedefs.JSONArray 143 ) -> collections.Sequence[user.DestinyMembership]: 144 return [self.deserialize_destiny_membership(membership) for membership in data]
Deserialize a raw JSON payload/array of destinyUserInfo.
Parameters
- payload (
aiobungie.typedefs.JSONArray): The JSON payload.
Returns
collections.Sequence[aiobungie.crates.user.DestinyMembership]: A sequence of Destiny 2 memberships.
146 def deserialize_user(self, data: typedefs.JSONObject) -> user.User: 147 primary_membership_id: typing.Optional[int] = None 148 if raw_primary_id := data.get("primaryMembershipId"): 149 primary_membership_id = int(raw_primary_id) 150 151 return user.User( 152 bungie=self.deserialize_bungie_user(data["bungieNetUser"]), 153 destiny=self.deserialize_destiny_memberships(data["destinyMemberships"]), 154 primary_membership_id=primary_membership_id, 155 )
Deserialize a raw JSON results of fetched user memberships and Bungie.net user its their id.
Parameters
- data (
aiobungie.typedefs.JSONObject): The JSON data/payload.
Returns
aiobungie.crates.User: A user object.
157 def deserialize_searched_user( 158 self, payload: typedefs.JSONObject 159 ) -> user.SearchableDestinyUser: 160 name: undefined.UndefinedOr[str] = undefined.UNDEFINED 161 if (raw_name := payload["bungieGlobalDisplayName"]) and not typedefs.is_unknown( 162 raw_name 163 ): 164 name = raw_name 165 166 code: typing.Optional[int] = None 167 if raw_code := payload.get("bungieGlobalDisplayNameCode"): 168 code = int(raw_code) 169 170 bungie_id: typing.Optional[int] = None 171 if raw_bungie_id := payload.get("bungieNetMembershipId"): 172 bungie_id = int(raw_bungie_id) 173 174 return user.SearchableDestinyUser( 175 name=name, 176 code=code, 177 bungie_id=bungie_id, 178 memberships=self.deserialize_destiny_memberships( 179 payload["destinyMemberships"] 180 ), 181 )
Deserialize the results of user search details.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.SearchableDestinyUser: The searched for Destiny 2 membership.
183 def deserialize_user_credentials( 184 self, payload: typedefs.JSONArray 185 ) -> collections.Sequence[user.UserCredentials]: 186 return [ 187 user.UserCredentials( 188 type=enums.CredentialType(int(creds["credentialType"])), 189 display_name=creds["credentialDisplayName"], 190 is_public=creds["isPublic"], 191 self_as_string=creds.get("credentialAsString", undefined.UNDEFINED), 192 ) 193 for creds in payload 194 ]
Deserialize a JSON array of Bungie user credentials.
Parameters
- payload (
aiobungie.typedefs.JSONArray): The JSON payload.
Returns
collections.Sequence[aiobungie.crates.UserCredentials]: A sequence of user's credentials.
196 def deserialize_user_themes( 197 self, payload: typedefs.JSONArray 198 ) -> collections.Sequence[user.UserThemes]: 199 return [ 200 user.UserThemes( 201 id=int(entry["userThemeId"]), 202 name=entry["userThemeName"] 203 if "userThemeName" in entry 204 else undefined.UNDEFINED, 205 description=entry["userThemeDescription"] 206 if "userThemeDescription" in entry 207 else undefined.UNDEFINED, 208 ) 209 for entry in payload 210 ]
Deserialize a raw JSON array of Bungie user themes.
Parameters
- payload (
aiobungie.typedefs.JSONArray): The JSON payload.
Returns
collections.Sequence[aiobungie.crates.user.UserThemes]: A sequence of bungie user themes.
212 def deserialize_clan(self, payload: typedefs.JSONObject) -> clans.Clan: 213 # This is kinda redundant 214 data = payload 215 216 # This is always outside the details. 217 current_user_map: typing.Optional[ 218 collections.Mapping[str, clans.ClanMember] 219 ] = None 220 if raw_current_user_map := payload.get("currentUserMemberMap"): 221 current_user_map = { 222 membership_type: self.deserialize_clan_member(membership) 223 for membership_type, membership in raw_current_user_map.items() 224 } 225 226 try: 227 data = payload["detail"] 228 except KeyError: 229 pass 230 231 id = data["groupId"] 232 name = data["name"] 233 created_at = data["creationDate"] 234 member_count = data["memberCount"] 235 about = data["about"] 236 motto = data["motto"] 237 is_public = data["isPublic"] 238 banner = assets.Image(str(data["bannerPath"])) 239 avatar = assets.Image(str(data["avatarPath"])) 240 tags = data["tags"] 241 type = data["groupType"] 242 243 features = data["features"] 244 features_obj = clans.ClanFeatures( 245 max_members=features["maximumMembers"], 246 max_membership_types=features["maximumMembershipsOfGroupType"], 247 capabilities=features["capabilities"], 248 membership_types=features["membershipTypes"], 249 invite_permissions=features["invitePermissionOverride"], 250 update_banner_permissions=features["updateBannerPermissionOverride"], 251 update_culture_permissions=features["updateCulturePermissionOverride"], 252 join_level=features["joinLevel"], 253 ) 254 255 information: typedefs.JSONObject = data["clanInfo"] 256 progression: collections.Mapping[int, progressions.Progression] = { 257 int(prog_hash): self.deserialize_progressions(prog) 258 for prog_hash, prog in information["d2ClanProgressions"].items() 259 } 260 261 founder: typedefs.NoneOr[clans.ClanMember] = None 262 if raw_founder := payload.get("founder"): 263 founder = self.deserialize_clan_member(raw_founder) 264 265 return clans.Clan( 266 net=self._net, 267 id=int(id), 268 name=name, 269 type=enums.GroupType(type), 270 created_at=time.clean_date(created_at), 271 member_count=member_count, 272 motto=motto, 273 about=about, 274 is_public=is_public, 275 banner=banner, 276 avatar=avatar, 277 tags=tags, 278 features=features_obj, 279 owner=founder, 280 progressions=progression, 281 call_sign=information["clanCallsign"], 282 banner_data=information["clanBannerData"], 283 chat_security=data["chatSecurity"], 284 conversation_id=int(data["conversationId"]), 285 allow_chat=data["allowChat"], 286 theme=data["theme"], 287 current_user_membership=current_user_map, 288 )
Deserialize a raw JSON payload of Bungie clan information.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.Clan: A clan owner.
290 def deserialize_clan_member(self, data: typedefs.JSONObject, /) -> clans.ClanMember: 291 destiny_user = self.deserialize_destiny_membership(data["destinyUserInfo"]) 292 return clans.ClanMember( 293 net=self._net, 294 last_seen_name=destiny_user.last_seen_name, 295 id=destiny_user.id, 296 name=destiny_user.name, 297 icon=destiny_user.icon, 298 last_online=time.from_timestamp(int(data["lastOnlineStatusChange"])), 299 group_id=int(data["groupId"]), 300 joined_at=time.clean_date(data["joinDate"]), 301 types=destiny_user.types, 302 is_public=destiny_user.is_public, 303 type=destiny_user.type, 304 code=destiny_user.code, 305 is_online=data["isOnline"], 306 crossave_override=destiny_user.crossave_override, 307 bungie=self.deserialize_partial_bungie_user(data["bungieNetUserInfo"]) 308 if "bungieNetUserInfo" in data 309 else None, 310 member_type=enums.ClanMemberType(int(data["memberType"])), 311 )
Deserialize a JSON payload of a clan member information.
Parameters
- data (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.ClanMember: A clan member.
313 def deserialize_clan_members( 314 self, data: typedefs.JSONObject, / 315 ) -> iterators.Iterator[clans.ClanMember]: 316 return iterators.Iterator( 317 [self.deserialize_clan_member(member) for member in data["results"]] 318 )
Deserialize a JSON payload of a clan members information.
Parameters
- data (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.iterators.Iterator[aiobungie.crates.ClanMember]: An iterator of clan members of the deserialized payload.
320 def deserialize_group_member( 321 self, payload: typedefs.JSONObject 322 ) -> clans.GroupMember: 323 member = payload["member"] 324 return clans.GroupMember( 325 net=self._net, 326 join_date=time.clean_date(member["joinDate"]), 327 group_id=int(member["groupId"]), 328 member_type=enums.ClanMemberType(member["memberType"]), 329 is_online=member["isOnline"], 330 last_online=time.from_timestamp(int(member["lastOnlineStatusChange"])), 331 inactive_memberships=payload.get("areAllMembershipsInactive", None), 332 member=self.deserialize_destiny_membership(member["destinyUserInfo"]), 333 group=self.deserialize_clan(payload["group"]), 334 )
Deserialize a JSON payload of group information for a member.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.typedefs.NoneOr[aiobungie.crates.GroupMember]: A group member. This can returnNoneif nothing was found.
352 def deserialize_clan_conversations( 353 self, payload: typedefs.JSONArray 354 ) -> collections.Sequence[clans.ClanConversation]: 355 return [self._deserialize_clan_conversation(conv) for conv in payload]
Deserialize a JSON array of a clan conversations information.
Parameters
- payload (
aiobungie.typedefs.JSONArray): The JSON payload.
Returns
collections.Sequence[aiobungie.crates.ClanConversation]: A sequence of clan conversations of the deserialized payload.
357 def deserialize_app_owner( 358 self, payload: typedefs.JSONObject 359 ) -> application.ApplicationOwner: 360 return application.ApplicationOwner( 361 net=self._net, 362 name=payload.get("bungieGlobalDisplayName", undefined.UNDEFINED), 363 id=int(payload["membershipId"]), 364 type=enums.MembershipType(payload["membershipType"]), 365 icon=assets.Image(str(payload["iconPath"])), 366 is_public=payload["isPublic"], 367 code=payload.get("bungieGlobalDisplayNameCode", None), 368 )
Deserialize a JSON payload of Bungie Developer portal application owner information.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.application.ApplicationOwner: An application owner.
370 def deserialize_app(self, payload: typedefs.JSONObject) -> application.Application: 371 return application.Application( 372 id=int(payload["applicationId"]), 373 name=payload["name"], 374 link=payload["link"], 375 status=payload["status"], 376 redirect_url=payload.get("redirectUrl", None), 377 created_at=time.clean_date(str(payload["creationDate"])), 378 published_at=time.clean_date(str(payload["firstPublished"])), 379 owner=self.deserialize_app_owner(payload["team"][0]["user"]), # type: ignore 380 scope=payload.get("scope", undefined.UNDEFINED), 381 )
Deserialize a JSON payload of Bungie Developer portal application information.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.application.Application: An application.
404 def deserialize_profile(self, payload: typedefs.JSONObject, /) -> profile.Profile: 405 payload = payload["data"] 406 id = int(payload["userInfo"]["membershipId"]) 407 name = payload["userInfo"]["displayName"] 408 is_public = payload["userInfo"]["isPublic"] 409 type = enums.MembershipType(payload["userInfo"]["membershipType"]) 410 last_played = time.clean_date(str(payload["dateLastPlayed"])) 411 character_ids = [int(cid) for cid in payload["characterIds"]] 412 power_cap = payload["currentSeasonRewardPowerCap"] 413 414 return profile.Profile( 415 id=int(id), 416 name=name, 417 is_public=is_public, 418 type=type, 419 last_played=last_played, 420 character_ids=character_ids, 421 power_cap=power_cap, 422 net=self._net, 423 )
Deserialize a JSON payload of Bungie.net profile information.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.Profile: A profile object of the deserialized payload.
425 def deserialize_profile_item( 426 self, payload: typedefs.JSONObject 427 ) -> profile.ProfileItemImpl: 428 instance_id: typing.Optional[int] = None 429 if raw_instance_id := payload.get("itemInstanceId"): 430 instance_id = int(raw_instance_id) 431 432 version_number: typing.Optional[int] = None 433 if raw_version := payload.get("versionNumber"): 434 version_number = int(raw_version) 435 436 transfer_status = enums.TransferStatus(payload["transferStatus"]) 437 438 return profile.ProfileItemImpl( 439 net=self._net, 440 hash=payload["itemHash"], 441 quantity=payload["quantity"], 442 bind_status=enums.ItemBindStatus(payload["bindStatus"]), 443 location=enums.ItemLocation(payload["location"]), 444 bucket=payload["bucketHash"], 445 transfer_status=transfer_status, 446 lockable=payload["lockable"], 447 state=enums.ItemState(payload["state"]), 448 dismantel_permissions=payload["dismantlePermission"], 449 is_wrapper=payload["isWrapper"], 450 instance_id=instance_id, 451 version_number=version_number, 452 ornament_id=payload.get("overrideStyleItemHash"), 453 )
Deserialize a JSON payload of a singular profile component item.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.ProfileItemImpl: Implementation of a Destiny 2 profile component item.
455 def deserialize_objectives(self, payload: typedefs.JSONObject) -> records.Objective: 456 return records.Objective( 457 net=self._net, 458 hash=payload["objectiveHash"], 459 visible=payload["visible"], 460 complete=payload["complete"], 461 completion_value=payload["completionValue"], 462 progress=payload.get("progress"), 463 destination_hash=payload.get("destinationHash"), 464 activity_hash=payload.get("activityHash"), 465 )
Deserialize a JSON payload of an objective found in a record profile component.
Parameters
- payload (
aiobungie.internal.helpers.JsonObject): The JSON payload.
Returns
aiobungie.crates.records.Objective: A record objective object.
467 def deserialize_records( 468 self, 469 payload: typedefs.JSONObject, 470 scores: typing.Optional[records.RecordScores] = None, 471 **nodes: int, 472 ) -> records.Record: 473 objectives: typing.Optional[list[records.Objective]] = None 474 interval_objectives: typing.Optional[list[records.Objective]] = None 475 record_state: typedefs.IntAnd[records.RecordState] 476 477 record_state = records.RecordState(payload["state"]) 478 479 if raw_objs := payload.get("objectives"): 480 objectives = [self.deserialize_objectives(obj) for obj in raw_objs] 481 482 if raw_interval_objs := payload.get("intervalObjectives"): 483 interval_objectives = [ 484 self.deserialize_objectives(obj) for obj in raw_interval_objs 485 ] 486 487 return records.Record( 488 scores=scores, 489 categories_node_hash=nodes.get("categories_hash", undefined.UNDEFINED), 490 seals_node_hash=nodes.get("seals_hash", undefined.UNDEFINED), 491 state=record_state, 492 objectives=objectives, 493 interval_objectives=interval_objectives, 494 redeemed_count=payload.get("intervalsRedeemedCount", 0), 495 completion_times=payload.get("completedCount", None), 496 reward_visibility=payload.get("rewardVisibilty", None), 497 )
Deserialize a JSON object of a profile record component.
Parameters
- payload (
aiobungie.internal.helpers.JsonObject): The JSON object payload - scores (
typing.Optional[records.RecordScores]): The records scores object. This exists only to keep the signature ofaiobungie.crates.CharacterRecordwith the record object. As it will always beNonein that object. - **nodes (
int): An int kwargs use to grab the node hashes while deserializing components.
Returns
aiobungie.records.Record: A standard implementation of a profile record component.
499 def deserialize_character_records( 500 self, 501 payload: typedefs.JSONObject, 502 scores: typing.Optional[records.RecordScores] = None, 503 record_hashes: typing.Optional[list[int]] = None, 504 ) -> records.CharacterRecord: 505 record = self.deserialize_records(payload, scores) 506 return records.CharacterRecord( 507 scores=scores, 508 categories_node_hash=record.categories_node_hash, 509 seals_node_hash=record.seals_node_hash, 510 state=record.state, 511 objectives=record.objectives, 512 interval_objectives=record.interval_objectives, 513 redeemed_count=payload.get("intervalsRedeemedCount", 0), 514 completion_times=payload.get("completedCount"), 515 reward_visibility=payload.get("rewardVisibilty"), 516 record_hashes=record_hashes or [], 517 )
Deserialize a JSON object of a profile character record component.
This almost does the same this as deserialize_records but
has more fields which can only be found in a character record.
Parameters
- payload (
aiobungie.internal.helpers.JsonObject): The JSON object payload
Returns
aiobungie.records.CharacterRecord: A standard implementation of a profile character record component.
519 def deserialize_character_dye(self, payload: typedefs.JSONObject) -> character.Dye: 520 return character.Dye( 521 channel_hash=payload["channelHash"], dye_hash=payload["dyeHash"] 522 )
Deserialize a JSON payload of a character's dye information.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.character.Dye: Information about a character dye object.
524 def deserialize_character_customization( 525 self, payload: typedefs.JSONObject 526 ) -> character.CustomizationOptions: 527 return character.CustomizationOptions( 528 personality=payload["personality"], 529 face=payload["face"], 530 skin_color=payload["skinColor"], 531 lip_color=payload["lipColor"], 532 eye_color=payload["eyeColor"], 533 hair_colors=payload.get("hairColors", []), 534 feature_colors=payload.get("featureColors", []), 535 decal_color=payload["decalColor"], 536 wear_helmet=payload["wearHelmet"], 537 hair_index=payload["hairIndex"], 538 feature_index=payload["featureIndex"], 539 decal_index=payload["decalIndex"], 540 )
Deserialize a JSON payload of a character customization information found in character render data profile component.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.character.CustomizationOptions: Information about a character customs object.
542 def deserialize_character_minimal_equipments( 543 self, payload: typedefs.JSONObject 544 ) -> character.MinimalEquipments: 545 dyes = None 546 if raw_dyes := payload.get("dyes"): 547 if raw_dyes: 548 dyes = [self.deserialize_character_dye(dye) for dye in raw_dyes] 549 return character.MinimalEquipments( 550 net=self._net, item_hash=payload["itemHash"], dyes=dyes 551 )
Deserialize a singular JSON peer view of equipment found in character render data profile component.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.character.MinimalEquipments: A minimal equipment object.
553 def deserialize_character_render_data( 554 self, payload: typedefs.JSONObject, / 555 ) -> character.RenderedData: 556 return character.RenderedData( 557 net=self._net, 558 customization=self.deserialize_character_customization( 559 payload["customization"] 560 ), 561 custom_dyes=[ 562 self.deserialize_character_dye(dye) 563 for dye in payload["customDyes"] 564 if dye 565 ], 566 equipment=[ 567 self.deserialize_character_minimal_equipments(equipment) 568 for equipment in payload["peerView"]["equipment"] 569 ], 570 )
Deserialize a JSON payload of a profile character render data component.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.RenderedData: A character rendered data profile component.
572 def deserialize_available_activity( 573 self, payload: typedefs.JSONObject 574 ) -> activity.AvailableActivity: 575 return activity.AvailableActivity( 576 hash=payload["activityHash"], 577 is_new=payload["isNew"], 578 is_completed=payload["isCompleted"], 579 is_visible=payload["isVisible"], 580 display_level=payload.get("displayLevel"), 581 recommended_light=payload.get("recommendedLight"), 582 difficulty=activity.Difficulty(payload["difficultyTier"]), 583 can_join=payload["canJoin"], 584 can_lead=payload["canLead"], 585 )
Deserialize a JSON payload of an available activities.
This method is used to deserialize an array of aiobungie.crates.CharacterActivity.available_activities.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.AvailableActivity: An available activity object.
587 def deserialize_character_activity( 588 self, payload: typedefs.JSONObject 589 ) -> activity.CharacterActivity: 590 current_mode: typing.Optional[enums.GameMode] = None 591 if raw_current_mode := payload.get("currentActivityModeType"): 592 current_mode = enums.GameMode(raw_current_mode) 593 594 current_mode_types: typing.Optional[collections.Sequence[enums.GameMode]] = None 595 if raw_current_modes := payload.get("currentActivityModeTypes"): 596 current_mode_types = [enums.GameMode(type_) for type_ in raw_current_modes] 597 598 return activity.CharacterActivity( 599 date_started=time.clean_date(payload["dateActivityStarted"]), 600 current_hash=payload["currentActivityHash"], 601 current_mode_hash=payload["currentActivityModeHash"], 602 current_mode=current_mode, 603 current_mode_hashes=payload.get("currentActivityModeHashes"), 604 current_mode_types=current_mode_types, 605 current_playlist_hash=payload.get("currentPlaylistActivityHash"), 606 last_story_hash=payload["lastCompletedStoryHash"], 607 available_activities=[ 608 self.deserialize_available_activity(activity_) 609 for activity_ in payload["availableActivities"] 610 ], 611 )
Deserialize a JSON payload of character activity profile component.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.CharacterActivity: A character activities component object.
613 def deserialize_profile_items( 614 self, payload: typedefs.JSONObject, / 615 ) -> list[profile.ProfileItemImpl]: 616 return [self.deserialize_profile_item(item) for item in payload["items"]]
Deserialize a JSON payload of profile items component information.
This may deserialize profileInventories or profileCurrencies or any
other alternatives.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
collections.Sequence[aiobungie.crates.ProfileItemImpl]: A profile component object that contains items of the deserialized payload.
659 def deserialize_progressions( 660 self, payload: typedefs.JSONObject 661 ) -> progressions.Progression: 662 return progressions.Progression( 663 hash=int(payload["progressionHash"]), 664 level=int(payload["level"]), 665 cap=int(payload["levelCap"]), 666 daily_limit=int(payload["dailyLimit"]), 667 weekly_limit=int(payload["weeklyLimit"]), 668 current_progress=int(payload["currentProgress"]), 669 daily_progress=int(payload["dailyProgress"]), 670 needed=int(payload["progressToNextLevel"]), 671 next_level=int(payload["nextLevelAt"]), 672 )
759 def deserialize_milestone( 760 self, payload: typedefs.JSONObject 761 ) -> milestones.Milestone: 762 start_date: typing.Optional[datetime.datetime] = None 763 if raw_start_date := payload.get("startDate"): 764 start_date = time.clean_date(raw_start_date) 765 766 end_date: typing.Optional[datetime.datetime] = None 767 if raw_end_date := payload.get("endDate"): 768 end_date = time.clean_date(raw_end_date) 769 770 rewards: typing.Optional[ 771 collections.Collection[milestones.MilestoneReward] 772 ] = None 773 if raw_rewards := payload.get("rewards"): 774 rewards = [ 775 self._deserialize_milestone_rewards(reward) for reward in raw_rewards 776 ] 777 778 activities: typing.Optional[ 779 collections.Sequence[milestones.MilestoneActivity] 780 ] = None 781 if raw_activities := payload.get("activities"): 782 activities = [ 783 self._deserialize_milestone_activity(active) 784 for active in raw_activities 785 ] 786 787 quests: typing.Optional[collections.Sequence[milestones.MilestoneQuest]] = None 788 if raw_quests := payload.get("availableQuests"): 789 quests = [ 790 self._deserialize_milestone_available_quest(quest) 791 for quest in raw_quests 792 ] 793 794 vendors: typing.Optional[ 795 collections.Sequence[milestones.MilestoneVendor] 796 ] = None 797 if raw_vendors := payload.get("vendors"): 798 vendors = [ 799 milestones.MilestoneVendor( 800 vendor_hash=vendor["vendorHash"], 801 preview_itemhash=vendor.get("previewItemHash"), 802 ) 803 for vendor in raw_vendors 804 ] 805 806 return milestones.Milestone( 807 hash=payload["milestoneHash"], 808 start_date=start_date, 809 end_date=end_date, 810 order=payload["order"], 811 rewards=rewards, 812 available_quests=quests, 813 activities=activities, 814 vendors=vendors, 815 )
869 def deserialize_character_progressions( 870 self, payload: typedefs.JSONObject 871 ) -> character.CharacterProgression: 872 progressions_ = { 873 int(prog_id): self.deserialize_progressions(prog) 874 for prog_id, prog in payload["progressions"].items() 875 } 876 877 factions = { 878 int(faction_id): self._deserialize_factions(faction) 879 for faction_id, faction in payload["factions"].items() 880 } 881 882 milestones_ = { 883 int(milestone_hash): self.deserialize_milestone(milestone) 884 for milestone_hash, milestone in payload["milestones"].items() 885 } 886 887 uninstanced_item_objectives = { 888 int(item_hash): [self.deserialize_objectives(ins) for ins in obj] 889 for item_hash, obj in payload["uninstancedItemObjectives"].items() 890 } 891 892 artifact = payload["seasonalArtifact"] 893 seasonal_artifact = season.CharacterScopedArtifact( 894 hash=artifact["artifactHash"], 895 points_used=artifact["pointsUsed"], 896 reset_count=artifact["resetCount"], 897 tiers=[ 898 self._deserialize_artifact_tiers(tier) for tier in artifact["tiers"] 899 ], 900 ) 901 checklists = payload["checklists"] 902 903 return character.CharacterProgression( 904 progressions=progressions_, 905 factions=factions, 906 checklists=checklists, 907 milestones=milestones_, 908 seasonal_artifact=seasonal_artifact, 909 uninstanced_item_objectives=uninstanced_item_objectives, 910 )
912 def deserialize_character_progressions_mapping( 913 self, payload: typedefs.JSONObject 914 ) -> collections.Mapping[int, character.CharacterProgression]: 915 character_progressions: collections.Mapping[ 916 int, character.CharacterProgression 917 ] = {} 918 for char_id, data in payload["data"].items(): 919 # A little hack to stop mypy complaining about Mapping <-> dict 920 character_progressions[int(char_id)] = self.deserialize_character_progressions(data) # type: ignore[index] 921 return character_progressions
923 def deserialize_characters_records( 924 self, 925 payload: typedefs.JSONObject, 926 ) -> collections.Mapping[int, records.CharacterRecord]: 927 return { 928 int(rec_id): self.deserialize_character_records( 929 rec, record_hashes=payload.get("featuredRecordHashes") 930 ) 931 for rec_id, rec in payload["records"].items() 932 }
934 def deserialize_profile_records( 935 self, payload: typedefs.JSONObject 936 ) -> collections.Mapping[int, records.Record]: 937 raw_profile_records = payload["data"] 938 scores = records.RecordScores( 939 current_score=raw_profile_records["score"], 940 legacy_score=raw_profile_records["legacyScore"], 941 lifetime_score=raw_profile_records["lifetimeScore"], 942 ) 943 return { 944 int(record_id): self.deserialize_records( 945 record, 946 scores, 947 categories_hash=raw_profile_records["recordCategoriesRootNodeHash"], 948 seals_hash=raw_profile_records["recordSealsRootNodeHash"], 949 ) 950 for record_id, record in raw_profile_records["records"].items() 951 }
986 def deserialize_craftables_component( 987 self, payload: typedefs.JSONObject 988 ) -> components.CraftablesComponent: 989 return components.CraftablesComponent( 990 net=self._net, 991 craftables={ 992 int(item_id): self._deserialize_craftable_item(item) 993 for item_id, item in payload["craftables"].items() 994 if item is not None 995 }, 996 crafting_root_node_hash=payload["craftingRootNodeHash"], 997 )
999 def deserialize_components( # noqa: C901 Too complex. 1000 self, payload: typedefs.JSONObject 1001 ) -> components.Component: 1002 profile_: typing.Optional[profile.Profile] = None 1003 if raw_profile := payload.get("profile"): 1004 profile_ = self.deserialize_profile(raw_profile) 1005 1006 profile_progression: typing.Optional[profile.ProfileProgression] = None 1007 if raw_profile_progression := payload.get("profileProgression"): 1008 profile_progression = self.deserialize_profile_progression( 1009 raw_profile_progression 1010 ) 1011 1012 profile_currencies: typing.Optional[ 1013 collections.Sequence[profile.ProfileItemImpl] 1014 ] = None 1015 if raw_profile_currencies := payload.get("profileCurrencies"): 1016 if "data" in raw_profile_currencies: 1017 profile_currencies = self.deserialize_profile_items( 1018 raw_profile_currencies["data"] 1019 ) 1020 1021 profile_inventories: typing.Optional[ 1022 collections.Sequence[profile.ProfileItemImpl] 1023 ] = None 1024 if raw_profile_inventories := payload.get("profileInventory"): 1025 if "data" in raw_profile_inventories: 1026 profile_inventories = self.deserialize_profile_items( 1027 raw_profile_inventories["data"] 1028 ) 1029 1030 profile_records: typing.Optional[ 1031 collections.Mapping[int, records.Record] 1032 ] = None 1033 1034 if raw_profile_records_ := payload.get("profileRecords"): 1035 profile_records = self.deserialize_profile_records(raw_profile_records_) 1036 1037 characters: typing.Optional[typing.Mapping[int, character.Character]] = None 1038 if raw_characters := payload.get("characters"): 1039 characters = self.deserialize_characters(raw_characters) 1040 1041 character_records: typing.Optional[ 1042 collections.Mapping[int, records.CharacterRecord] 1043 ] = None 1044 1045 if raw_character_records := payload.get("characterRecords"): 1046 # Had to do it in two steps.. 1047 to_update: typedefs.JSONObject = {} 1048 for _, data in raw_character_records["data"].items(): 1049 for record_id, record in data.items(): 1050 to_update[record_id] = record 1051 1052 character_records = { 1053 int(rec_id): self.deserialize_character_records( 1054 rec, record_hashes=to_update.get("featuredRecordHashes") 1055 ) 1056 for rec_id, rec in to_update["records"].items() 1057 } 1058 1059 character_equipments: typing.Optional[ 1060 collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]] 1061 ] = None 1062 if raw_character_equips := payload.get("characterEquipment"): 1063 character_equipments = self.deserialize_character_equipments( 1064 raw_character_equips 1065 ) 1066 1067 character_inventories: typing.Optional[ 1068 collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]] 1069 ] = None 1070 if raw_character_inventories := payload.get("characterInventories"): 1071 if "data" in raw_character_inventories: 1072 character_inventories = self.deserialize_character_equipments( 1073 raw_character_inventories 1074 ) 1075 1076 character_activities: typing.Optional[ 1077 collections.Mapping[int, activity.CharacterActivity] 1078 ] = None 1079 if raw_char_acts := payload.get("characterActivities"): 1080 character_activities = self.deserialize_character_activities(raw_char_acts) 1081 1082 character_render_data: typing.Optional[ 1083 collections.Mapping[int, character.RenderedData] 1084 ] = None 1085 if raw_character_render_data := payload.get("characterRenderData"): 1086 character_render_data = self.deserialize_characters_render_data( 1087 raw_character_render_data 1088 ) 1089 1090 character_progressions: typing.Optional[ 1091 collections.Mapping[int, character.CharacterProgression] 1092 ] = None 1093 1094 if raw_character_progressions := payload.get("characterProgressions"): 1095 character_progressions = self.deserialize_character_progressions_mapping( 1096 raw_character_progressions 1097 ) 1098 1099 profile_string_vars: typing.Optional[collections.Mapping[int, int]] = None 1100 if raw_profile_string_vars := payload.get("profileStringVariables"): 1101 profile_string_vars = raw_profile_string_vars["data"]["integerValuesByHash"] 1102 1103 character_string_vars: typing.Optional[ 1104 collections.Mapping[int, collections.Mapping[int, int]] 1105 ] = None 1106 if raw_character_string_vars := payload.get("characterStringVariables"): 1107 character_string_vars = { 1108 int(char_id): data["integerValuesByHash"] 1109 for char_id, data in raw_character_string_vars["data"].items() 1110 } 1111 1112 metrics: typing.Optional[ 1113 collections.Sequence[ 1114 collections.Mapping[ 1115 int, tuple[bool, typing.Optional[records.Objective]] 1116 ] 1117 ] 1118 ] = None 1119 root_node_hash: typing.Optional[int] = None 1120 1121 if raw_metrics := payload.get("metrics"): 1122 root_node_hash = raw_metrics["data"]["metricsRootNodeHash"] 1123 metrics = [ 1124 { 1125 int(metrics_hash): ( 1126 data["invisible"], 1127 self.deserialize_objectives(data["objectiveProgress"]) 1128 if "objectiveProgress" in data 1129 else None, 1130 ) 1131 for metrics_hash, data in raw_metrics["data"]["metrics"].items() 1132 } 1133 ] 1134 transitory: typing.Optional[fireteams.FireteamParty] = None 1135 if raw_transitory := payload.get("profileTransitoryData"): 1136 if "data" in raw_transitory: 1137 transitory = self.deserialize_fireteam_party(raw_transitory["data"]) 1138 1139 item_components: typing.Optional[components.ItemsComponent] = None 1140 if raw_item_components := payload.get("itemComponents"): 1141 item_components = self.deserialize_items_component(raw_item_components) 1142 1143 profile_plugsets: typing.Optional[ 1144 collections.Mapping[int, collections.Sequence[items.PlugItemState]] 1145 ] = None 1146 1147 if raw_profile_plugs := payload.get("profilePlugSets"): 1148 profile_plugsets = { 1149 int(index): [self.deserialize_plug_item_state(state) for state in data] 1150 for index, data in raw_profile_plugs["data"]["plugs"].items() 1151 } 1152 1153 character_plugsets: typing.Optional[ 1154 collections.Mapping[ 1155 int, collections.Mapping[int, collections.Sequence[items.PlugItemState]] 1156 ] 1157 ] = None 1158 if raw_char_plugsets := payload.get("characterPlugSets"): 1159 character_plugsets = { 1160 int(char_id): { 1161 int(index): [ 1162 self.deserialize_plug_item_state(state) for state in data 1163 ] 1164 for index, data in inner["plugs"].items() 1165 } 1166 for char_id, inner in raw_char_plugsets["data"].items() 1167 } 1168 1169 character_collectibles: typing.Optional[ 1170 collections.Mapping[int, items.Collectible] 1171 ] = None 1172 if raw_character_collectibles := payload.get("characterCollectibles"): 1173 character_collectibles = { 1174 int(char_id): self._deserialize_collectible(data) 1175 for char_id, data in raw_character_collectibles["data"].items() 1176 } 1177 1178 profile_collectibles: typing.Optional[items.Collectible] = None 1179 if raw_profile_collectibles := payload.get("profileCollectibles"): 1180 profile_collectibles = self._deserialize_collectible( 1181 raw_profile_collectibles["data"] 1182 ) 1183 1184 profile_nodes: typing.Optional[collections.Mapping[int, records.Node]] = None 1185 if raw_profile_nodes := payload.get("profilePresentationNodes"): 1186 profile_nodes = { 1187 int(node_hash): self._deserialize_node(node) 1188 for node_hash, node in raw_profile_nodes["data"]["nodes"].items() 1189 } 1190 1191 character_nodes: typing.Optional[ 1192 collections.Mapping[int, collections.Mapping[int, records.Node]] 1193 ] = None 1194 if raw_character_nodes := payload.get("characterPresentationNodes"): 1195 character_nodes = { 1196 int(char_id): { 1197 int(node_hash): self._deserialize_node(node) 1198 for node_hash, node in each_character["nodes"].items() 1199 } 1200 for char_id, each_character in raw_character_nodes["data"].items() 1201 } 1202 1203 platform_silver: typing.Optional[ 1204 collections.Mapping[str, profile.ProfileItemImpl] 1205 ] = None 1206 if raw_platform_silver := payload.get("platformSilver"): 1207 if "data" in raw_platform_silver: 1208 platform_silver = { 1209 platform_name: self.deserialize_profile_item(item) 1210 for platform_name, item in raw_platform_silver["data"][ 1211 "platformSilver" 1212 ].items() 1213 } 1214 1215 character_currency_lookups: typing.Optional[ 1216 collections.Mapping[int, collections.Sequence[items.Currency]] 1217 ] = None 1218 if raw_char_lookups := payload.get("characterCurrencyLookups"): 1219 if "data" in raw_char_lookups: 1220 character_currency_lookups = { 1221 int(char_id): self._deserialize_currencies(currencie) 1222 for char_id, currencie in raw_char_lookups["data"].items() 1223 } 1224 1225 character_craftables: typing.Optional[ 1226 collections.Mapping[int, components.CraftablesComponent] 1227 ] = None 1228 if raw_character_craftables := payload.get("characterCraftables"): 1229 if "data" in raw_character_craftables: 1230 character_craftables = { 1231 int(char_id): self.deserialize_craftables_component(craftable) 1232 for char_id, craftable in raw_character_craftables["data"].items() 1233 } 1234 1235 return components.Component( 1236 profiles=profile_, 1237 profile_progression=profile_progression, 1238 profile_currencies=profile_currencies, 1239 profile_inventories=profile_inventories, 1240 profile_records=profile_records, 1241 characters=characters, 1242 character_records=character_records, 1243 character_equipments=character_equipments, 1244 character_inventories=character_inventories, 1245 character_activities=character_activities, 1246 character_render_data=character_render_data, 1247 character_progressions=character_progressions, 1248 profile_string_variables=profile_string_vars, 1249 character_string_variables=character_string_vars, 1250 metrics=metrics, 1251 root_node_hash=root_node_hash, 1252 transitory=transitory, 1253 item_components=item_components, 1254 profile_plugsets=profile_plugsets, 1255 character_plugsets=character_plugsets, 1256 character_collectibles=character_collectibles, 1257 profile_collectibles=profile_collectibles, 1258 profile_nodes=profile_nodes, 1259 character_nodes=character_nodes, 1260 platform_silver=platform_silver, 1261 character_currency_lookups=character_currency_lookups, 1262 character_craftables=character_craftables, 1263 )
Deserialize a JSON payload of Bungie.net profile components information.
Parameters
- payload (
aiobungie.internal.helpers.JsonObject): The JSON payload.
Returns
aiobungie.crates.Component: A component implementation that includes all other components of the deserialized payload.
1265 def deserialize_items_component( 1266 self, payload: typedefs.JSONObject 1267 ) -> components.ItemsComponent: 1268 instances: typing.Optional[ 1269 collections.Sequence[collections.Mapping[int, items.ItemInstance]] 1270 ] = None 1271 if raw_instances := payload.get("instances"): 1272 instances = [ 1273 { 1274 int(ins_id): self.deserialize_instanced_item(item) 1275 for ins_id, item in raw_instances["data"].items() 1276 } 1277 ] 1278 1279 render_data: typing.Optional[ 1280 collections.Mapping[int, tuple[bool, dict[int, int]]] 1281 ] = None 1282 if raw_render_data := payload.get("renderData"): 1283 render_data = { 1284 int(ins_id): (data["useCustomDyes"], data["artRegions"]) 1285 for ins_id, data in raw_render_data["data"].items() 1286 } 1287 1288 stats: typing.Optional[collections.Mapping[int, items.ItemStatsView]] = None 1289 if raw_stats := payload.get("stats"): 1290 builder: collections.Mapping[int, items.ItemStatsView] = {} 1291 for ins_id, stat in raw_stats["data"].items(): 1292 for _, items_ in stat.items(): 1293 builder[int(ins_id)] = self.deserialize_item_stats_view(items_) # type: ignore[index] 1294 stats = builder 1295 1296 sockets: typing.Optional[ 1297 collections.Mapping[int, collections.Sequence[items.ItemSocket]] 1298 ] = None 1299 if raw_sockets := payload.get("sockets"): 1300 sockets = { 1301 int(ins_id): [ 1302 self.deserialize_item_socket(socket) for socket in item["sockets"] 1303 ] 1304 for ins_id, item in raw_sockets["data"].items() 1305 } 1306 1307 objeectives: typing.Optional[ 1308 collections.Mapping[int, collections.Sequence[records.Objective]] 1309 ] = None 1310 if raw_objectives := payload.get("objectives"): 1311 objeectives = { 1312 int(ins_id): [self.deserialize_objectives(objective)] 1313 for ins_id, data in raw_objectives["data"].items() 1314 for objective in data["objectives"] 1315 } 1316 1317 perks: typing.Optional[ 1318 collections.Mapping[int, collections.Collection[items.ItemPerk]] 1319 ] = None 1320 if raw_perks := payload.get("perks"): 1321 perks = { 1322 int(ins_id): [ 1323 self.deserialize_item_perk(perk) for perk in item["perks"] 1324 ] 1325 for ins_id, item in raw_perks["data"].items() 1326 } 1327 1328 plug_states: typing.Optional[collections.Sequence[items.PlugItemState]] = None 1329 if raw_plug_states := payload.get("plugStates"): 1330 pending_states: list[items.PlugItemState] = [] 1331 for _, plug in raw_plug_states["data"].items(): 1332 pending_states.append(self.deserialize_plug_item_state(plug)) 1333 plug_states = pending_states 1334 1335 reusable_plugs: typing.Optional[ 1336 collections.Mapping[int, collections.Sequence[items.PlugItemState]] 1337 ] = None 1338 if raw_re_plugs := payload.get("reusablePlugs"): 1339 reusable_plugs = { 1340 int(ins_id): [ 1341 self.deserialize_plug_item_state(state) for state in inner 1342 ] 1343 for ins_id, plug in raw_re_plugs["data"].items() 1344 for inner in list(plug["plugs"].values()) 1345 } 1346 1347 plug_objectives: typing.Optional[ 1348 collections.Mapping[ 1349 int, collections.Mapping[int, collections.Collection[records.Objective]] 1350 ] 1351 ] = None 1352 if raw_plug_objectives := payload.get("plugObjectives"): 1353 plug_objectives = { 1354 int(ins_id): { 1355 int(obj_hash): [self.deserialize_objectives(obj) for obj in objs] 1356 for obj_hash, objs in inner["objectivesPerPlug"].items() 1357 } 1358 for ins_id, inner in raw_plug_objectives["data"].items() 1359 } 1360 1361 return components.ItemsComponent( 1362 sockets=sockets, 1363 stats=stats, 1364 render_data=render_data, 1365 instances=instances, 1366 objectives=objeectives, 1367 perks=perks, 1368 plug_states=plug_states, 1369 reusable_plugs=reusable_plugs, 1370 plug_objectives=plug_objectives, 1371 )
Deserialize a JSON objects within the itemComponents key.`
1373 def deserialize_character_component( # type: ignore[call-arg] 1374 self, payload: typedefs.JSONObject 1375 ) -> components.CharacterComponent: 1376 character_: typing.Optional[character.Character] = None 1377 if raw_singuler_character := payload.get("character"): 1378 character_ = self.deserialize_character(raw_singuler_character["data"]) 1379 1380 inventory: typing.Optional[collections.Sequence[profile.ProfileItemImpl]] = None 1381 if raw_inventory := payload.get("inventory"): 1382 if "data" in raw_inventory: 1383 inventory = self.deserialize_profile_items(raw_inventory["data"]) 1384 1385 activities: typing.Optional[activity.CharacterActivity] = None 1386 if raw_activities := payload.get("activities"): 1387 activities = self.deserialize_character_activity(raw_activities["data"]) 1388 1389 equipment: typing.Optional[collections.Sequence[profile.ProfileItemImpl]] = None 1390 if raw_equipments := payload.get("equipment"): 1391 equipment = self.deserialize_profile_items(raw_equipments["data"]) 1392 1393 progressions_: typing.Optional[character.CharacterProgression] = None 1394 if raw_progressions := payload.get("progressions"): 1395 progressions_ = self.deserialize_character_progressions( 1396 raw_progressions["data"] 1397 ) 1398 1399 render_data: typing.Optional[character.RenderedData] = None 1400 if raw_render_data := payload.get("renderData"): 1401 render_data = self.deserialize_character_render_data( 1402 raw_render_data["data"] 1403 ) 1404 1405 character_records: typing.Optional[ 1406 collections.Mapping[int, records.CharacterRecord] 1407 ] = None 1408 if raw_char_records := payload.get("records"): 1409 character_records = self.deserialize_characters_records( 1410 raw_char_records["data"] 1411 ) 1412 1413 item_components: typing.Optional[components.ItemsComponent] = None 1414 if raw_item_components := payload.get("itemComponents"): 1415 item_components = self.deserialize_items_component(raw_item_components) 1416 1417 nodes: typing.Optional[collections.Mapping[int, records.Node]] = None 1418 if raw_nodes := payload.get("presentationNodes"): 1419 nodes = { 1420 int(node_hash): self._deserialize_node(node) 1421 for node_hash, node in raw_nodes["data"]["nodes"].items() 1422 } 1423 1424 collectibles: typing.Optional[items.Collectible] = None 1425 if raw_collectibles := payload.get("collectibles"): 1426 collectibles = self._deserialize_collectible(raw_collectibles["data"]) 1427 1428 currency_lookups: typing.Optional[collections.Sequence[items.Currency]] = None 1429 if raw_currencies := payload.get("currencyLookups"): 1430 if "data" in raw_currencies: 1431 currency_lookups = self._deserialize_currencies(raw_currencies) 1432 1433 return components.CharacterComponent( 1434 activities=activities, 1435 equipment=equipment, 1436 inventory=inventory, 1437 progressions=progressions_, 1438 render_data=render_data, 1439 character=character_, 1440 character_records=character_records, 1441 profile_records=None, 1442 item_components=item_components, 1443 currency_lookups=currency_lookups, 1444 collectibles=collectibles, 1445 nodes=nodes, 1446 )
Deserialize a JSON payload of Destiny 2 character component.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.CharacterComponent: A character component.
1473 def deserialize_inventory_results( 1474 self, payload: typedefs.JSONObject 1475 ) -> iterators.Iterator[entity.SearchableEntity]: 1476 suggested_words: list[str] = payload["suggestedWords"] 1477 1478 def _check_unknown(s: str) -> undefined.UndefinedOr[str]: 1479 return s if not typedefs.is_unknown(s) else undefined.UNDEFINED 1480 1481 return iterators.Iterator( 1482 [ 1483 entity.SearchableEntity( 1484 net=self._net, 1485 hash=data["hash"], 1486 entity_type=data["entityType"], 1487 weight=data["weight"], 1488 suggested_words=suggested_words, 1489 name=data["displayProperties"]["name"], 1490 has_icon=data["displayProperties"]["hasIcon"], 1491 description=_check_unknown( 1492 data["displayProperties"]["description"] 1493 ), 1494 icon=assets.Image(data["displayProperties"]["icon"]), 1495 ) 1496 for data in payload["results"]["results"] 1497 ] 1498 )
Deserialize results of searched Destiny2 entities.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.iterators.Iterator[aiobungie.crates.SearchableEntity]: An iterator over the found searched entities.
1527 def deserialize_inventory_entity( # noqa: C901 Too complex. 1528 self, payload: typedefs.JSONObject, / 1529 ) -> entity.InventoryEntity: 1530 props = self._set_entity_attrs(payload) 1531 objects = self._deserialize_inventory_item_objects(payload) 1532 1533 collectible_hash: typing.Optional[int] = None 1534 if raw_collectible_hash := payload.get("collectibleHash"): 1535 collectible_hash = int(raw_collectible_hash) 1536 1537 secondary_icon: undefined.UndefinedOr[assets.Image] = undefined.UNDEFINED 1538 if raw_second_icon := payload.get("secondaryIcon"): 1539 secondary_icon = assets.Image(raw_second_icon) 1540 1541 secondary_overlay: undefined.UndefinedOr[assets.Image] = undefined.UNDEFINED 1542 if raw_second_overlay := payload.get("secondaryOverlay"): 1543 secondary_overlay = assets.Image(raw_second_overlay) 1544 1545 secondary_special: undefined.UndefinedOr[assets.Image] = undefined.UNDEFINED 1546 if raw_second_special := payload.get("secondarySpecial"): 1547 secondary_special = assets.Image(raw_second_special) 1548 1549 screenshot: undefined.UndefinedOr[assets.Image] = undefined.UNDEFINED 1550 if raw_screenshot := payload.get("screenshot"): 1551 screenshot = assets.Image(raw_screenshot) 1552 1553 watermark_icon: typing.Optional[assets.Image] = None 1554 if raw_watermark_icon := payload.get("iconWatermark"): 1555 watermark_icon = assets.Image(raw_watermark_icon) 1556 1557 watermark_shelved: typing.Optional[assets.Image] = None 1558 if raw_watermark_shelved := payload.get("iconWatermarkShelved"): 1559 watermark_shelved = assets.Image(raw_watermark_shelved) 1560 1561 about: undefined.UndefinedOr[str] = undefined.UNDEFINED 1562 if (raw_about := payload.get("flavorText")) and not typedefs.is_unknown( 1563 raw_about 1564 ): 1565 about = raw_about 1566 1567 ui_item_style: undefined.UndefinedOr[str] = undefined.UNDEFINED 1568 if ( 1569 raw_ui_style := payload.get("uiItemDisplayStyle") 1570 ) and not typedefs.is_unknown(raw_ui_style): 1571 ui_item_style = raw_ui_style 1572 1573 tier_and_name: undefined.UndefinedOr[str] = undefined.UNDEFINED 1574 if ( 1575 raw_tier_and_name := payload.get("itemTypeAndTierDisplayName") 1576 ) and not typedefs.is_unknown(raw_tier_and_name): 1577 tier_and_name = raw_tier_and_name 1578 1579 type_name: undefined.UndefinedOr[str] = undefined.UNDEFINED 1580 if ( 1581 raw_type_name := payload.get("itemTypeDisplayName") 1582 ) and not typedefs.is_unknown(raw_type_name): 1583 type_name = raw_type_name 1584 1585 display_source: undefined.UndefinedOr[str] = undefined.UNDEFINED 1586 if ( 1587 raw_display_source := payload.get("displaySource") 1588 ) and not typedefs.is_unknown(raw_display_source): 1589 display_source = raw_display_source 1590 1591 lorehash: typing.Optional[int] = None 1592 if raw_lore_hash := payload.get("loreHash"): 1593 lorehash = int(raw_lore_hash) 1594 1595 summary_hash: typing.Optional[int] = None 1596 if raw_summary_hash := payload.get("summaryItemHash"): 1597 summary_hash = raw_summary_hash 1598 1599 breaker_type_hash: typing.Optional[int] = None 1600 if raw_breaker_type_hash := payload.get("breakerTypeHash"): 1601 breaker_type_hash = int(raw_breaker_type_hash) 1602 1603 damage_types: typing.Optional[collections.Sequence[int]] = None 1604 if raw_damage_types := payload.get("damageTypes"): 1605 damage_types = [int(type_) for type_ in raw_damage_types] 1606 1607 damagetype_hashes: typing.Optional[collections.Sequence[int]] = None 1608 if raw_damagetype_hashes := payload.get("damageTypeHashes"): 1609 damagetype_hashes = [int(type_) for type_ in raw_damagetype_hashes] 1610 1611 default_damagetype_hash: typing.Optional[int] = None 1612 if raw_defaultdmg_hash := payload.get("defaultDamageTypeHash"): 1613 default_damagetype_hash = int(raw_defaultdmg_hash) 1614 1615 emblem_objective_hash: typing.Optional[int] = None 1616 if raw_emblem_obj_hash := payload.get("emblemObjectiveHash"): 1617 emblem_objective_hash = int(raw_emblem_obj_hash) 1618 1619 tier_type: typing.Optional[enums.TierType] = None 1620 tier: typing.Optional[enums.ItemTier] = None 1621 bucket_hash: typing.Optional[int] = None 1622 recovery_hash: typing.Optional[int] = None 1623 tier_name: undefined.UndefinedOr[str] = undefined.UNDEFINED 1624 isinstance_item: bool = False 1625 expire_tool_tip: undefined.UndefinedOr[str] = undefined.UNDEFINED 1626 expire_in_orbit_message: undefined.UndefinedOr[str] = undefined.UNDEFINED 1627 suppress_expiration: bool = False 1628 max_stack_size: typing.Optional[int] = None 1629 stack_label: undefined.UndefinedOr[str] = undefined.UNDEFINED 1630 1631 if inventory := payload.get("inventory"): 1632 tier_type = enums.TierType(int(inventory["tierType"])) 1633 tier = enums.ItemTier(int(inventory["tierTypeHash"])) 1634 bucket_hash = int(inventory["bucketTypeHash"]) 1635 recovery_hash = int(inventory["recoveryBucketTypeHash"]) 1636 tier_name = inventory["tierTypeName"] 1637 isinstance_item = inventory["isInstanceItem"] 1638 suppress_expiration = inventory["suppressExpirationWhenObjectivesComplete"] 1639 max_stack_size = int(inventory["maxStackSize"]) 1640 1641 try: 1642 stack_label = inventory["stackUniqueLabel"] 1643 except KeyError: 1644 pass 1645 1646 return entity.InventoryEntity( 1647 net=self._net, 1648 collectible_hash=collectible_hash, 1649 name=props.name, 1650 about=about, 1651 emblem_objective_hash=emblem_objective_hash, 1652 suppress_expiration=suppress_expiration, 1653 max_stack_size=max_stack_size, 1654 stack_label=stack_label, 1655 tier=tier, 1656 tier_type=tier_type, 1657 tier_name=tier_name, 1658 bucket_hash=bucket_hash, 1659 recovery_bucket_hash=recovery_hash, 1660 isinstance_item=isinstance_item, 1661 expire_in_orbit_message=expire_in_orbit_message, 1662 expiration_tooltip=expire_tool_tip, 1663 lore_hash=lorehash, 1664 type_and_tier_name=tier_and_name, 1665 summary_hash=summary_hash, 1666 ui_display_style=ui_item_style, 1667 type_name=type_name, 1668 breaker_type_hash=breaker_type_hash, 1669 description=props.description, 1670 display_source=display_source, 1671 hash=props.hash, 1672 damage_types=damage_types, 1673 index=props.index, 1674 icon=props.icon, 1675 has_icon=props.has_icon, 1676 screenshot=screenshot, 1677 watermark_icon=watermark_icon, 1678 watermark_shelved=watermark_shelved, 1679 secondary_icon=secondary_icon, 1680 secondary_overlay=secondary_overlay, 1681 secondary_special=secondary_special, 1682 type=enums.ItemType(int(payload["itemType"])), 1683 trait_hashes=[int(id_) for id_ in payload.get("traitHashes", [])], 1684 trait_ids=[trait for trait in payload.get("traitIds", [])], 1685 category_hashes=[int(hash_) for hash_ in payload["itemCategoryHashes"]], 1686 item_class=enums.Class(int(payload["classType"])), 1687 sub_type=enums.ItemSubType(int(payload["itemSubType"])), 1688 breaker_type=int(payload["breakerType"]), 1689 default_damagetype=int(payload["defaultDamageType"]), 1690 default_damagetype_hash=default_damagetype_hash, 1691 damagetype_hashes=damagetype_hashes, 1692 tooltip_notifications=payload["tooltipNotifications"], 1693 not_transferable=payload["nonTransferrable"], 1694 allow_actions=payload["allowActions"], 1695 is_equippable=payload["equippable"], 1696 objects=objects, 1697 background_colors=payload.get("backgroundColor", {}), 1698 season_hash=payload.get("seasonHash"), 1699 has_postmaster_effect=payload["doesPostmasterPullHaveSideEffects"], 1700 )
Deserialize a JSON payload of an inventory entity item information.
This can be any item from DestinyInventoryItemDefinition definition.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.InventoryEntity: An entity item.
1702 def deserialize_objective_entity( 1703 self, payload: typedefs.JSONObject, / 1704 ) -> entity.ObjectiveEntity: 1705 props = self._set_entity_attrs(payload) 1706 return entity.ObjectiveEntity( 1707 net=self._net, 1708 hash=props.hash, 1709 index=props.index, 1710 description=props.description, 1711 name=props.name, 1712 has_icon=props.has_icon, 1713 icon=props.icon, 1714 unlock_value_hash=payload["unlockValueHash"], 1715 completion_value=payload["completionValue"], 1716 scope=entity.GatingScope(int(payload["scope"])), 1717 location_hash=payload["locationHash"], 1718 allowed_negative_value=payload["allowNegativeValue"], 1719 allowed_value_change=payload["allowValueChangeWhenCompleted"], 1720 counting_downward=payload["isCountingDownward"], 1721 value_style=entity.ValueUIStyle(int(payload["valueStyle"])), 1722 progress_description=payload["progressDescription"], 1723 perks=payload["perks"], 1724 stats=payload["stats"], 1725 minimum_visibility=payload["minimumVisibilityThreshold"], 1726 allow_over_completion=payload["allowOvercompletion"], 1727 show_value_style=payload["showValueOnComplete"], 1728 display_only_objective=payload["isDisplayOnlyObjective"], 1729 complete_value_style=entity.ValueUIStyle( 1730 int(payload["completedValueStyle"]) 1731 ), 1732 progress_value_style=entity.ValueUIStyle( 1733 int(payload["inProgressValueStyle"]) 1734 ), 1735 ui_label=payload["uiLabel"], 1736 ui_style=entity.ObjectiveUIStyle(int(payload["uiStyle"])), 1737 )
Deserialize a JSON payload of an objective entity information.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.ObjectiveEntity: An objective entity.
1765 def deserialize_activity( 1766 self, 1767 payload: typedefs.JSONObject, 1768 /, 1769 ) -> activity.Activity: 1770 period = time.clean_date(payload["period"]) 1771 details = payload["activityDetails"] 1772 ref_id = int(details["referenceId"]) 1773 instance_id = int(details["instanceId"]) 1774 mode = enums.GameMode(details["mode"]) 1775 modes = [enums.GameMode(int(mode_)) for mode_ in details["modes"]] 1776 is_private = details["isPrivate"] 1777 membership_type = enums.MembershipType(int(details["membershipType"])) 1778 1779 # Since we're using the same fields for post activity method 1780 # this check is required since post activity doesn't values values 1781 values = self._deserialize_activity_values(payload["values"]) 1782 1783 return activity.Activity( 1784 net=self._net, 1785 hash=ref_id, 1786 instance_id=instance_id, 1787 mode=mode, 1788 modes=modes, 1789 is_private=is_private, 1790 membership_type=membership_type, 1791 occurred_at=period, 1792 values=values, 1793 )
Deserialize a JSON payload of an activity history information.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.Activity: An activity.
1795 def deserialize_activities( 1796 self, payload: typedefs.JSONObject 1797 ) -> iterators.Iterator[activity.Activity]: 1798 return iterators.Iterator( 1799 [ 1800 self.deserialize_activity(activity_) 1801 for activity_ in payload["activities"] 1802 ] 1803 )
Deserialize a JSON payload of an array of activity history information.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.iterators.Iterator[aiobungie.crates.Activity]: Am iterator over activity objects of the deserialized payload.
1805 def deserialize_extended_weapon_values( 1806 self, payload: typedefs.JSONObject 1807 ) -> activity.ExtendedWeaponValues: 1808 assists: typing.Optional[int] = None 1809 if raw_assists := payload["values"].get("uniqueWeaponAssists"): 1810 assists = raw_assists["basic"]["value"] 1811 assists_damage: typing.Optional[int] = None 1812 1813 if raw_assists_damage := payload["values"].get("uniqueWeaponAssistDamage"): 1814 assists_damage = raw_assists_damage["basic"]["value"] 1815 1816 return activity.ExtendedWeaponValues( 1817 reference_id=int(payload["referenceId"]), 1818 kills=payload["values"]["uniqueWeaponKills"]["basic"]["value"], 1819 precision_kills=payload["values"]["uniqueWeaponPrecisionKills"]["basic"][ 1820 "value" 1821 ], 1822 assists=assists, 1823 assists_damage=assists_damage, 1824 precision_kills_percentage=( 1825 payload["values"]["uniqueWeaponKillsPrecisionKills"]["basic"]["value"], 1826 payload["values"]["uniqueWeaponKillsPrecisionKills"]["basic"][ 1827 "displayValue" 1828 ], 1829 ), 1830 )
Deserialize values of extended weapons JSON object.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.ExtendedWeaponValues: Information about an extended weapon values.
1853 def deserialize_post_activity_player( 1854 self, payload: typedefs.JSONObject, / 1855 ) -> activity.PostActivityPlayer: 1856 player = payload["player"] 1857 1858 class_hash: typedefs.NoneOr[int] = None 1859 if (class_hash := player.get("classHash")) is not None: 1860 class_hash = class_hash 1861 1862 race_hash: typedefs.NoneOr[int] = None 1863 if (race_hash := player.get("raceHash")) is not None: 1864 race_hash = race_hash 1865 1866 gender_hash: typedefs.NoneOr[int] = None 1867 if (gender_hash := player.get("genderHash")) is not None: 1868 gender_hash = gender_hash 1869 1870 character_class: undefined.UndefinedOr[str] = undefined.UNDEFINED 1871 if ( 1872 character_class := player.get("characterClass") 1873 ) and not typedefs.is_unknown(character_class): 1874 character_class = character_class 1875 1876 character_level: typedefs.NoneOr[int] = None 1877 if (character_level := player.get("characterLevel")) is not None: 1878 character_level = character_level 1879 1880 return activity.PostActivityPlayer( 1881 standing=int(payload["standing"]), 1882 score=int(payload["score"]["basic"]["value"]), 1883 character_id=payload["characterId"], 1884 destiny_user=self.deserialize_destiny_membership(player["destinyUserInfo"]), 1885 character_class=character_class, 1886 character_level=character_level, 1887 race_hash=race_hash, 1888 gender_hash=gender_hash, 1889 class_hash=class_hash, 1890 light_level=int(player["lightLevel"]), 1891 emblem_hash=int(player["emblemHash"]), 1892 values=self._deserialize_activity_values(payload["values"]), 1893 extended_values=self._deserialize_extended_values(payload["extended"]), 1894 )
Deserialize a JSON payload of a post activity player information.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.PostActivityPlayer: A post activity player object.
1906 def deserialize_post_activity( 1907 self, payload: typedefs.JSONObject 1908 ) -> activity.PostActivity: 1909 period = time.clean_date(payload["period"]) 1910 details = payload["activityDetails"] 1911 ref_id = int(details["referenceId"]) 1912 instance_id = int(details["instanceId"]) 1913 mode = enums.GameMode(details["mode"]) 1914 modes = [enums.GameMode(int(mode_)) for mode_ in details["modes"]] 1915 is_private = details["isPrivate"] 1916 membership_type = enums.MembershipType(int(details["membershipType"])) 1917 return activity.PostActivity( 1918 net=self._net, 1919 hash=ref_id, 1920 membership_type=membership_type, 1921 instance_id=instance_id, 1922 mode=mode, 1923 modes=modes, 1924 is_private=is_private, 1925 occurred_at=period, 1926 starting_phase=int(payload["startingPhaseIndex"]), 1927 players=[ 1928 self.deserialize_post_activity_player(player) 1929 for player in payload["entries"] 1930 ], 1931 teams=[ 1932 self._deserialize_post_activity_team(team) for team in payload["teams"] 1933 ], 1934 )
Deserialize a JSON payload of a post activity information.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.PostActivity: A post activity object.
1972 def deserialize_aggregated_activity( 1973 self, payload: typedefs.JSONObject 1974 ) -> activity.AggregatedActivity: 1975 return activity.AggregatedActivity( 1976 hash=int(payload["activityHash"]), 1977 values=self._deserialize_aggregated_activity_values(payload["values"]), 1978 )
Deserialize a JSON payload of an aggregated activity.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.AggregatedActivity: An aggregated activity object.
1980 def deserialize_aggregated_activities( 1981 self, payload: typedefs.JSONObject 1982 ) -> iterators.Iterator[activity.AggregatedActivity]: 1983 return iterators.Iterator( 1984 [ 1985 self.deserialize_aggregated_activity(activity) 1986 for activity in payload["activities"] 1987 ] 1988 )
Deserialize a JSON payload of an array of aggregated activities.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.iterators.Iterator[aiobungie.crates.AggregatedActivity]: An iterator over aggregated activities objects.
1990 def deserialize_linked_profiles( 1991 self, payload: typedefs.JSONObject 1992 ) -> profile.LinkedProfile: 1993 bungie_user = self.deserialize_partial_bungie_user(payload["bnetMembership"]) 1994 error_profiles_vec: typing.MutableSequence[user.DestinyMembership] = [] 1995 profiles_vec: typing.MutableSequence[user.DestinyMembership] = [] 1996 1997 if raw_profile := payload.get("profiles"): 1998 for pfile in raw_profile: 1999 profiles_vec.append(self.deserialize_destiny_membership(pfile)) 2000 2001 if raw_profiles_with_errors := payload.get("profilesWithErrors"): 2002 for raw_error_pfile in raw_profiles_with_errors: 2003 if error_pfile := raw_error_pfile.get("infoCard"): 2004 error_profiles_vec.append( 2005 self.deserialize_destiny_membership(error_pfile) 2006 ) 2007 2008 return profile.LinkedProfile( 2009 net=self._net, 2010 bungie=bungie_user, 2011 profiles=profiles_vec, 2012 profiles_with_errors=error_profiles_vec, 2013 )
Deserialize a JSON payload of Bungie.net hard linked profile information.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.LinkedProfile: A hard linked profile.
2029 def deserialize_public_milestone_content( 2030 self, payload: typedefs.JSONObject 2031 ) -> milestones.MilestoneContent: 2032 items_categoris: typedefs.NoneOr[milestones.MilestoneItems] = None 2033 if raw_categories := payload.get("itemCategories"): 2034 for item in raw_categories: 2035 title = undefined.UNDEFINED 2036 if raw_title := item.get("title"): 2037 if raw_title != typedefs.Unknown: 2038 title = raw_title 2039 if raw_hashes := item.get("itemHashes"): 2040 hashes: collections.Sequence[int] = raw_hashes 2041 2042 items_categoris = milestones.MilestoneItems(title=title, hashes=hashes) 2043 2044 about = undefined.UNDEFINED 2045 if (raw_about := payload["about"]) != typedefs.Unknown: 2046 about = raw_about 2047 2048 status = undefined.UNDEFINED 2049 if (raw_status := payload["status"]) != typedefs.Unknown: 2050 status = raw_status 2051 2052 tips: typing.MutableSequence[undefined.UndefinedOr[str]] = [] 2053 if raw_tips := payload.get("tips"): 2054 for raw_tip in raw_tips: 2055 if raw_tip == typedefs.Unknown: 2056 raw_tip = undefined.UNDEFINED 2057 tips.append(raw_tip) 2058 2059 return milestones.MilestoneContent( 2060 about=about, status=status, tips=tips, items=items_categoris 2061 )
Deserialize a JSON payload of milestone content information.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.MilestoneContent: A milestone content.
2063 def deserialize_friend(self, payload: typedefs.JSONObject, /) -> friends.Friend: 2064 name = undefined.UNDEFINED 2065 if (raw_name := payload["bungieGlobalDisplayName"]) != typedefs.Unknown: 2066 name = raw_name 2067 2068 bungie_user: typedefs.NoneOr[user.BungieUser] = None 2069 2070 if raw_bungie_user := payload.get("bungieNetUser"): 2071 bungie_user = self.deserialize_bungie_user(raw_bungie_user) 2072 2073 return friends.Friend( 2074 net=self._net, 2075 id=int(payload["lastSeenAsMembershipId"]), 2076 name=name, 2077 code=payload.get("bungieGlobalDisplayNameCode"), 2078 relationship=enums.Relationship(payload["relationship"]), 2079 user=bungie_user, 2080 online_status=enums.Presence(payload["onlineStatus"]), 2081 online_title=payload["onlineTitle"], 2082 type=enums.MembershipType(payload["lastSeenAsBungieMembershipType"]), 2083 )
Deserialize a JSON payload of a Bungie friend information.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.Friend: A friend.
2085 def deserialize_friends( 2086 self, payload: typedefs.JSONObject 2087 ) -> collections.Sequence[friends.Friend]: 2088 mut_seq: typing.MutableSequence[friends.Friend] = [] 2089 if raw_friends := payload.get("friends"): 2090 for friend in raw_friends: 2091 mut_seq.append(self.deserialize_friend(friend)) 2092 return mut_seq
Deserialize a JSON sequence of Bungie friends information.
This is usually used to deserialize the incoming/outgoing friend requests.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
collections.Sequence[aiobungie.crates.Friend]: A sequence of friends.
2094 def deserialize_friend_requests( 2095 self, payload: typedefs.JSONObject 2096 ) -> friends.FriendRequestView: 2097 incoming: typing.MutableSequence[friends.Friend] = [] 2098 outgoing: typing.MutableSequence[friends.Friend] = [] 2099 2100 if raw_incoming_requests := payload.get("incomingRequests"): 2101 for incoming_request in raw_incoming_requests: 2102 incoming.append(self.deserialize_friend(incoming_request)) 2103 2104 if raw_outgoing_requests := payload.get("outgoingRequests"): 2105 for outgoing_request in raw_outgoing_requests: 2106 outgoing.append(self.deserialize_friend(outgoing_request)) 2107 2108 return friends.FriendRequestView(incoming=incoming, outgoing=outgoing)
Deserialize a JSON sequence of Bungie friend requests information.
This is used for incoming/outgoing friend requests.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
collections.Sequence[aiobungie.crates.FriendRequestView]: A sequence of incoming and outgoing friends.
2133 def deserialize_fireteams( 2134 self, payload: typedefs.JSONObject 2135 ) -> typedefs.NoneOr[collections.Sequence[fireteams.Fireteam]]: 2136 fireteams_: typing.MutableSequence[fireteams.Fireteam] = [] 2137 2138 result: list[typedefs.JSONObject] 2139 if not (result := payload["results"]): 2140 return None 2141 for elem in result: 2142 fireteams_.append( 2143 self._set_fireteam_fields( 2144 elem, total_results=int(payload["totalResults"]) 2145 ) 2146 ) 2147 return fireteams_
Deserialize a JSON sequence of Bungie fireteams information.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
collections.Sequence[aiobungie.crates.Fireteam]: A sequence of fireteam.
2149 def deserialize_fireteam_destiny_users( 2150 self, payload: typedefs.JSONObject 2151 ) -> fireteams.FireteamUser: 2152 destiny_obj = self.deserialize_destiny_membership(payload) 2153 # We could helpers.just return a DestinyMembership object but this is 2154 # missing the fireteam display name and id fields. 2155 return fireteams.FireteamUser( 2156 net=self._net, 2157 id=destiny_obj.id, 2158 code=destiny_obj.code, 2159 icon=destiny_obj.icon, 2160 types=destiny_obj.types, 2161 type=destiny_obj.type, 2162 is_public=destiny_obj.is_public, 2163 crossave_override=destiny_obj.crossave_override, 2164 name=destiny_obj.name, 2165 last_seen_name=destiny_obj.last_seen_name, 2166 fireteam_display_name=payload["FireteamDisplayName"], 2167 fireteam_membership_id=enums.MembershipType( 2168 payload["FireteamMembershipType"] 2169 ), 2170 )
Deserialize a JSON payload of Bungie fireteam destiny users information.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.FireteamUser: A fireteam user.
2172 def deserialize_fireteam_members( 2173 self, payload: typedefs.JSONObject, *, alternatives: bool = False 2174 ) -> collections.Sequence[fireteams.FireteamMember]: 2175 members_: list[fireteams.FireteamMember] = [] 2176 if members := payload.get("Members" if not alternatives else "Alternates"): 2177 for member in members: 2178 bungie_fields = self.deserialize_partial_bungie_user(member) 2179 members_fields = fireteams.FireteamMember( 2180 destiny_user=self.deserialize_fireteam_destiny_users(member), 2181 has_microphone=member["hasMicrophone"], 2182 character_id=int(member["characterId"]), 2183 date_joined=time.clean_date(member["dateJoined"]), 2184 last_platform_invite_date=time.clean_date( 2185 member["lastPlatformInviteAttemptDate"] 2186 ), 2187 last_platform_invite_result=int( 2188 member["lastPlatformInviteAttemptResult"] 2189 ), 2190 net=self._net, 2191 name=bungie_fields.name, 2192 id=bungie_fields.id, 2193 icon=bungie_fields.icon, 2194 is_public=bungie_fields.is_public, 2195 crossave_override=bungie_fields.crossave_override, 2196 types=bungie_fields.types, 2197 type=bungie_fields.type, 2198 ) 2199 members_.append(members_fields) 2200 return members_
Deserialize a JSON sequence of Bungie fireteam members information.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload. - alternatives (
bool): If set toTrue, Then it will deserialize thealternativesdata in the payload. If not the it will just deserialize themembersdata.
Returns
collections.Sequence[aiobungie.crates.FireteamUser]: A sequence of the fireteam members.
2202 def deserialize_available_fireteams( 2203 self, 2204 data: typedefs.JSONObject, 2205 *, 2206 no_results: bool = False, 2207 ) -> typing.Union[ 2208 fireteams.AvailableFireteam, collections.Sequence[fireteams.AvailableFireteam] 2209 ]: 2210 fireteams_: list[fireteams.AvailableFireteam] = [] 2211 2212 # This needs to be used outside the results 2213 # JSON key. 2214 if no_results: 2215 payload = data.copy() 2216 2217 if (results := payload.get("results")) is not None: 2218 for fireteam in results: 2219 found_fireteams = self._set_fireteam_fields(fireteam["Summary"]) 2220 fireteams_fields = fireteams.AvailableFireteam( 2221 id=found_fireteams.id, 2222 group_id=found_fireteams.group_id, 2223 platform=found_fireteams.platform, 2224 activity_type=found_fireteams.activity_type, 2225 is_immediate=found_fireteams.is_immediate, 2226 is_public=found_fireteams.is_public, 2227 is_valid=found_fireteams.is_valid, 2228 owner_id=found_fireteams.owner_id, 2229 player_slot_count=found_fireteams.player_slot_count, 2230 available_player_slots=found_fireteams.available_player_slots, 2231 available_alternate_slots=found_fireteams.available_alternate_slots, 2232 title=found_fireteams.title, 2233 date_created=found_fireteams.date_created, 2234 locale=found_fireteams.locale, 2235 last_modified=found_fireteams.last_modified, 2236 total_results=found_fireteams.total_results, 2237 members=self.deserialize_fireteam_members(payload), 2238 alternatives=self.deserialize_fireteam_members( 2239 payload, alternatives=True 2240 ), 2241 ) 2242 if no_results: 2243 return fireteams_fields 2244 else: 2245 fireteams_.append(fireteams_fields) 2246 return fireteams_
Deserialize a JSON payload of a sequence of/fireteam information.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload. - no_results (
bool): Whether to deserialize the data fromresultsin the payload or not.
Returns
typing.Union[aiobungie.crates.fireteams.AvailableFireteam, collections.Sequence[aiobungie.crates.fireteams.AvailableFireteam]]# noqa (E501): An available fireteam or a sequence of available fireteam.
2248 def deserialize_fireteam_party( 2249 self, payload: typedefs.JSONObject 2250 ) -> fireteams.FireteamParty: 2251 last_destination_hash: typing.Optional[int] = None 2252 if raw_dest_hash := payload.get("lastOrbitedDestinationHash"): 2253 last_destination_hash = int(raw_dest_hash) 2254 2255 return fireteams.FireteamParty( 2256 members=[ 2257 self._deserialize_fireteam_party_member(member) 2258 for member in payload["partyMembers"] 2259 ], 2260 activity=self._deserialize_fireteam_party_current_activity( 2261 payload["currentActivity"] 2262 ), 2263 settings=self._deserialize_fireteam_party_settings(payload["joinability"]), 2264 last_destination_hash=last_destination_hash, 2265 tracking=payload["tracking"], 2266 )
Deserialize a JSON payload of profileTransitory component response.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.FireteamParty: A fireteam party object of the current fireteam.
2312 def deserialize_seasonal_artifact( 2313 self, payload: typedefs.JSONObject 2314 ) -> season.Artifact: 2315 if raw_artifact := payload.get("seasonalArtifact"): 2316 if points := raw_artifact.get("pointProgression"): 2317 points_prog = progressions.Progression( 2318 hash=points["progressionHash"], 2319 level=points["level"], 2320 cap=points["levelCap"], 2321 daily_limit=points["dailyLimit"], 2322 weekly_limit=points["weeklyLimit"], 2323 current_progress=points["currentProgress"], 2324 daily_progress=points["dailyProgress"], 2325 needed=points["progressToNextLevel"], 2326 next_level=points["nextLevelAt"], 2327 ) 2328 2329 if bonus := raw_artifact.get("powerBonusProgression"): 2330 power_bonus_prog = progressions.Progression( 2331 hash=bonus["progressionHash"], 2332 level=bonus["level"], 2333 cap=bonus["levelCap"], 2334 daily_limit=bonus["dailyLimit"], 2335 weekly_limit=bonus["weeklyLimit"], 2336 current_progress=bonus["currentProgress"], 2337 daily_progress=bonus["dailyProgress"], 2338 needed=bonus["progressToNextLevel"], 2339 next_level=bonus["nextLevelAt"], 2340 ) 2341 artifact = season.Artifact( 2342 net=self._net, 2343 hash=raw_artifact["artifactHash"], 2344 power_bonus=raw_artifact["powerBonus"], 2345 acquired_points=raw_artifact["pointsAcquired"], 2346 bonus=power_bonus_prog, 2347 points=points_prog, 2348 ) 2349 return artifact
Deserialize a JSON payload of a Destiny 2 seasonal artifact information.
Parameters
- payload (
aiobungie.internal.helpers.JsonObject): The JSON payload.
Returns
aiobungie.crates.Artifact: A seasonal artifact.
2351 def deserialize_profile_progression( 2352 self, payload: typedefs.JSONObject 2353 ) -> profile.ProfileProgression: 2354 return profile.ProfileProgression( 2355 artifact=self.deserialize_seasonal_artifact(payload["data"]), 2356 checklist={ 2357 int(check_id): checklists 2358 for check_id, checklists in payload["data"]["checklists"].items() 2359 }, 2360 )
Deserialize a JSON payload of a profile progression component.
Parameters
- payload (
aiobungie.internal.helpers.JsonObject): The JSON payload.
Returns
aiobungie.crates.ProfileProgression: A profile progression component.
2362 def deserialize_instanced_item( 2363 self, payload: typedefs.JSONObject 2364 ) -> items.ItemInstance: 2365 damage_type_hash: typing.Optional[int] = None 2366 if raw_damagetype_hash := payload.get("damageTypeHash"): 2367 damage_type_hash = int(raw_damagetype_hash) 2368 2369 required_hashes: typing.Optional[collections.Collection[int]] = None 2370 if raw_required_hashes := payload.get("unlockHashesRequiredToEquip"): 2371 required_hashes = [int(raw_hash) for raw_hash in raw_required_hashes] 2372 2373 breaker_type: typing.Optional[items.ItemBreakerType] = None 2374 if raw_break_type := payload.get("breakerType"): 2375 breaker_type = items.ItemBreakerType(int(raw_break_type)) 2376 2377 breaker_type_hash: typing.Optional[int] = None 2378 if raw_break_type_hash := payload.get("breakerTypeHash"): 2379 breaker_type_hash = int(raw_break_type_hash) 2380 2381 energy: typing.Optional[items.ItemEnergy] = None 2382 if raw_energy := payload.get("energy"): 2383 energy = self.deserialize_item_energy(raw_energy) 2384 2385 primary_stats = None 2386 if raw_primary_stats := payload.get("primaryStat"): 2387 primary_stats = self.deserialize_item_stats_view(raw_primary_stats) 2388 2389 return items.ItemInstance( 2390 damage_type=enums.DamageType(int(payload["damageType"])), 2391 damage_type_hash=damage_type_hash, 2392 primary_stat=primary_stats, 2393 item_level=int(payload["itemLevel"]), 2394 quality=int(payload["quality"]), 2395 is_equipped=payload["isEquipped"], 2396 can_equip=payload["canEquip"], 2397 equip_required_level=int(payload["equipRequiredLevel"]), 2398 required_equip_unlock_hashes=required_hashes, 2399 cant_equip_reason=int(payload["cannotEquipReason"]), 2400 breaker_type=breaker_type, 2401 breaker_type_hash=breaker_type_hash, 2402 energy=energy, 2403 )
Deserialize a JSON object into an instanced item.
Parameters
- payload (
aiobungie.internal.helpers.JsonObject): The JSON payload.
Returns
aiobungie.crates.ItemInstance: An instanced item object.
2405 def deserialize_item_energy(self, payload: typedefs.JSONObject) -> items.ItemEnergy: 2406 energy_hash: typing.Optional[int] = None 2407 if raw_energy_hash := payload.get("energyTypeHash"): 2408 energy_hash = int(raw_energy_hash) 2409 2410 return items.ItemEnergy( 2411 hash=energy_hash, 2412 type=items.ItemEnergyType(int(payload["energyType"])), 2413 capacity=int(payload["energyCapacity"]), 2414 used_energy=int(payload["energyUsed"]), 2415 unused_energy=int(payload["energyUnused"]), 2416 )
2418 def deserialize_item_perk(self, payload: typedefs.JSONObject) -> items.ItemPerk: 2419 perk_hash: typing.Optional[int] = None 2420 if raw_perk_hash := payload.get("perkHash"): 2421 perk_hash = int(raw_perk_hash) 2422 2423 return items.ItemPerk( 2424 hash=perk_hash, 2425 icon=assets.Image(payload["iconPath"]), 2426 is_active=payload["isActive"], 2427 is_visible=payload["visible"], 2428 )
2430 def deserialize_item_socket(self, payload: typedefs.JSONObject) -> items.ItemSocket: 2431 plug_hash: typing.Optional[int] = None 2432 if raw_plug_hash := payload.get("plugHash"): 2433 plug_hash = int(raw_plug_hash) 2434 2435 enable_fail_indexes: typing.Optional[list[int]] = None 2436 if raw_indexes := payload.get("enableFailIndexes"): 2437 enable_fail_indexes = [int(index) for index in raw_indexes] 2438 2439 return items.ItemSocket( 2440 plug_hash=plug_hash, 2441 is_enabled=payload["isEnabled"], 2442 enable_fail_indexes=enable_fail_indexes, 2443 is_visible=payload.get("visible"), 2444 )
2453 def deserialize_plug_item_state( 2454 self, payload: typedefs.JSONObject 2455 ) -> items.PlugItemState: 2456 item_hash: typing.Optional[int] = None 2457 if raw_item_hash := payload.get("plugItemHash"): 2458 item_hash = int(raw_item_hash) 2459 2460 insert_fail_indexes: typedefs.NoneOr[list[int]] = None 2461 if raw_fail_indexes := payload.get("insertFailIndexes"): 2462 insert_fail_indexes = [int(k) for k in raw_fail_indexes] 2463 2464 enable_fail_indexes: typedefs.NoneOr[list[int]] = None 2465 if raw_enabled_indexes := payload.get("enableFailIndexes"): 2466 enable_fail_indexes = [int(k) for k in raw_enabled_indexes] 2467 2468 return items.PlugItemState( 2469 item_hash=item_hash, 2470 insert_fail_indexes=insert_fail_indexes, 2471 enable_fail_indexes=enable_fail_indexes, 2472 is_enabled=payload["enabled"], 2473 can_insert=payload["canInsert"], 2474 )
67@typing.final 68class FireteamActivity(int, enums.Enum): 69 """An enum for the fireteam activities.""" 70 71 ALL = 0 72 CRUCIBLE = 2 73 TRIALS_OF_OSIRIS = 3 74 NIGHTFALL = 4 75 ANY = 5 76 GAMBIT = 6 77 BLIND_WELL = 7 78 NIGHTMARE_HUNTS = 12 79 ALTARS_OF_SORROWS = 14 80 DUNGEON = 15 81 RAID_LW = 20 82 RAID_GOS = 21 83 RAID_DSC = 22 84 EXO_CHALLENGE = 23 85 S12_WRATHBORN = 24 86 EMPIRE_HUNTS = 25 87 S13_BATTLEGROUNDS = 26 88 EXOTIC_QUEST = 27 89 RAID_VOG = 28 90 S14_EXPUNGE = 30 91 S15_ASTRAL_ALIGNMENT = 31 92 S15_SHATTERED_RELAM = 32 93 SHATTERED_THRONE = 33 94 PROPHECY = 34 95 PIT_OF_HERESY = 35 96 DOE = 36 97 """Dares of Eternity.""" 98 DUNGEON_GOA = 37 99 """Grasp of Avarice.""" 100 VOW_OF_THE_DISCPILE = 38 101 CAMPAIGN = 39 102 WELLSPRING = 40 103 S16_BATTLEGROUNDS = 41 104 S17_NIGHTMARE_CONTAINMENT = 44 105 S17_SEVER = 45
An enum for the fireteam activities.
131@typing.final 132class FireteamDate(int, enums.Enum): 133 """An enum for fireteam date ranges.""" 134 135 ALL = 0 136 NOW = 1 137 TODAY = 2 138 TWO_DAYS = 3 139 THIS_WEEK = 4
An enum for fireteam date ranges.
108@typing.final 109class FireteamLanguage(str, enums.Enum): 110 """An enum for fireteams languages filters.""" 111 112 ALL = "" 113 ENGLISH = "en" 114 FRENCH = "fr" 115 ESPANOL = "es" 116 DEUTSCH = "de" 117 ITALIAN = "it" 118 JAPANESE = "ja" 119 PORTUGUESE = "pt-br" 120 RUSSIAN = "ru" 121 POLISH = "pl" 122 KOREAN = "ko" 123 # ? China 124 ZH_CHT = "zh-cht" 125 ZH_CHS = "zh-chs" 126 127 def __str__(self) -> str: 128 return str(self.value)
An enum for fireteams languages filters.
Inherited Members
- builtins.str
- encode
- replace
- split
- rsplit
- join
- capitalize
- casefold
- title
- center
- count
- expandtabs
- find
- partition
- index
- ljust
- lower
- lstrip
- rfind
- rindex
- rjust
- rstrip
- rpartition
- splitlines
- strip
- swapcase
- translate
- upper
- startswith
- endswith
- removeprefix
- removesuffix
- isascii
- islower
- isupper
- istitle
- isspace
- isdecimal
- isdigit
- isnumeric
- isalpha
- isalnum
- isidentifier
- isprintable
- zfill
- format
- format_map
- maketrans
54@typing.final 55class FireteamPlatform(int, enums.Enum): 56 """An enum for fireteam related to bungie fireteams. 57 This is different from the normal `aiobungie.MembershipType`. 58 """ 59 60 ANY = 0 61 PSN_NETWORK = 1 62 XBOX_LIVE = 2 63 STEAM = 4 64 STADIA = 5
An enum for fireteam related to bungie fireteams.
This is different from the normal aiobungie.MembershipType.
91class Flag(__enum.Flag): 92 """Builtin Python enum flag with extra handlings.""" 93 94 # Needs to type this here for mypy 95 _value_: int 96 97 @property 98 def name(self) -> str: # type: ignore[override] 99 if self._name_ is None: 100 self._name_ = f"UNKNOWN {self._value_}" 101 102 return self._name_ 103 104 @property 105 def value(self) -> int: # type: ignore[override] 106 return self._value_ 107 108 def __str__(self) -> str: 109 return self.name 110 111 def __repr__(self) -> str: 112 return f"<{type(self).__name__}.{self.name}: {self._value_!s}>" 113 114 def __int__(self) -> int: 115 return int(self.value) 116 117 def __or__(self, other: typing.Union[Flag, int]) -> Flag: 118 return self.__class__(self._value_ | int(other)) 119 120 def __xor__(self, other: typing.Union[Flag, int]) -> Flag: 121 return self.__class__(self._value_ ^ int(other)) 122 123 def __and__(self, other: typing.Union[Flag, int]) -> Flag: 124 return self.__class__(other & int(other)) 125 126 def __invert__(self) -> Flag: 127 return self.__class__(~self._value_) 128 129 def __contains__(self, other: typing.Union[Flag, int]) -> bool: 130 return self.value & int(other) == int(other)
Builtin Python enum flag with extra handlings.
137@attrs.define(auto_exc=True) 138class Forbidden(HTTPException): 139 """Exception that's raised for when status code 403 occurs.""" 140 141 http_status: http.HTTPStatus = attrs.field( 142 default=http.HTTPStatus.FORBIDDEN, init=False 143 )
Exception that's raised for when status code 403 occurs.
2def __init__(self, *, error_code, throttle_seconds, url, body, headers, message, error_status, message_data): 3 self.error_code = error_code 4 self.throttle_seconds = throttle_seconds 5 self.url = url 6 self.body = body 7 self.headers = headers 8 self.message = message 9 self.error_status = error_status 10 self.message_data = message_data 11 self.http_status = attr_dict['http_status'].default 12 BaseException.__init__(self, self.error_code,self.throttle_seconds,self.url,self.body,self.headers,self.message,self.error_status,self.message_data)
Method generated by attrs for class Forbidden.
Inherited Members
- builtins.BaseException
- with_traceback
- args
259@typing.final 260class GameMode(int, Enum): 261 """An Enum for all available gamemodes in Destiny 2.""" 262 263 NONE = 0 264 STORY = 2 265 STRIKE = 3 266 RAID = 4 267 ALLPVP = 5 268 PATROL = 6 269 ALLPVE = 7 270 RESERVED9 = 9 271 CONTROL = 10 272 RESERVED11 = 11 273 CLASH = 12 274 RESERVED13 = 13 275 CRIMSONDOUBLES = 15 276 NIGHTFALL = 16 277 HEROICNIGHTFALL = 17 278 ALLSTRIKES = 18 279 IRONBANNER = 19 280 RESERVED20 = 20 281 RESERVED21 = 21 282 RESERVED22 = 22 283 RESERVED24 = 24 284 ALLMAYHEM = 25 285 RESERVED26 = 26 286 RESERVED27 = 27 287 RESERVED28 = 28 288 RESERVED29 = 29 289 RESERVED30 = 30 290 SUPREMACY = 31 291 PRIVATEMATCHESALL = 32 292 SURVIVAL = 37 293 COUNTDOWN = 38 294 TRIALSOFTHENINE = 39 295 SOCIAL = 40 296 TRIALSCOUNTDOWN = 41 297 TRIALSSURVIVAL = 42 298 IRONBANNERCONTROL = 43 299 IRONBANNERCLASH = 44 300 IRONBANNERSUPREMACY = 45 301 SCOREDNIGHTFALL = 46 302 SCOREDHEROICNIGHTFALL = 47 303 RUMBLE = 48 304 ALLDOUBLES = 49 305 DOUBLES = 50 306 PRIVATEMATCHESCLASH = 51 307 PRIVATEMATCHESCONTROL = 52 308 PRIVATEMATCHESSUPREMACY = 53 309 PRIVATEMATCHESCOUNTDOWN = 54 310 PRIVATEMATCHESSURVIVAL = 55 311 PRIVATEMATCHESMAYHEM = 56 312 PRIVATEMATCHESRUMBLE = 57 313 HEROICADVENTURE = 58 314 SHOWDOWN = 59 315 LOCKDOWN = 60 316 SCORCHED = 61 317 SCORCHEDTEAM = 62 318 GAMBIT = 63 319 ALLPVECOMPETITIVE = 64 320 BREAKTHROUGH = 65 321 BLACKARMORYRUN = 66 322 SALVAGE = 67 323 IRONBANNERSALVAGE = 68 324 PVPCOMPETITIVE = 69 325 PVPQUICKPLAY = 70 326 CLASHQUICKPLAY = 71 327 CLASHCOMPETITIVE = 72 328 CONTROLQUICKPLAY = 73 329 CONTROLCOMPETITIVE = 74 330 GAMBITPRIME = 75 331 RECKONING = 76 332 MENAGERIE = 77 333 VEXOFFENSIVE = 78 334 NIGHTMAREHUNT = 79 335 ELIMINATION = 80 336 MOMENTUM = 81 337 DUNGEON = 82 338 SUNDIAL = 83 339 TRIALS_OF_OSIRIS = 84 340 DARES = 85 341 OFFENSIVE = 86 342 LOSTSECTOR = 87 343 RIFT = 88 344 ZONECONTROL = 89 345 IRONBANNERRIFT = 90
An Enum for all available gamemodes in Destiny 2.
58@typing.final 59class GatingScope(int, enums.Enum): 60 """An enum represents restrictive type of gating that is being performed by an entity. 61 62 This is useful as a shortcut to avoid a lot of lookups when determining whether the gating on an Entity 63 applies to everyone equally, or to their specific Profile or Character states. 64 """ 65 66 NONE = 0 67 GLOBAL = 1 68 CLAN = 2 69 PROFILE = 3 70 CHARACTER = 4 71 ITEM = 5 72 ASSUMED_WORST_CASE = 6
An enum represents restrictive type of gating that is being performed by an entity.
This is useful as a shortcut to avoid a lot of lookups when determining whether the gating on an Entity applies to everyone equally, or to their specific Profile or Character states.
476@typing.final 477class Gender(int, Enum): 478 """An Enum for Destiny Genders.""" 479 480 MALE = 0 481 FEMALE = 1 482 UNKNOWN = 2
An Enum for Destiny Genders.
645@typing.final 646class GroupType(int, Enum): 647 """An enums for the known bungie group types.""" 648 649 GENERAL = 0 650 CLAN = 1
An enums for the known bungie group types.
79@attrs.define(auto_exc=True) 80class HTTPError(AiobungieError): 81 """Base HTTP request errors exception.""" 82 83 message: str 84 """The error message.""" 85 86 http_status: http.HTTPStatus 87 """The response status."""
Base HTTP request errors exception.
2def __init__(self, message, http_status): 3 self.message = message 4 self.http_status = http_status 5 BaseException.__init__(self, self.message,self.http_status)
Method generated by attrs for class HTTPError.
Inherited Members
- builtins.BaseException
- with_traceback
- args
90@attrs.define(auto_exc=True, kw_only=True) 91class HTTPException(HTTPError): 92 """An in-depth HTTP exception that's raised with more information.""" 93 94 error_code: int 95 """The returned Bungie error status code.""" 96 97 http_status: http.HTTPStatus 98 """The request response http status.""" 99 100 throttle_seconds: int 101 """The Bungie response throttle seconds.""" 102 103 url: typing.Optional[typedefs.StrOrURL] 104 """The URL/endpoint caused this error.""" 105 106 body: typing.Any 107 """The response body.""" 108 109 headers: multidict.CIMultiDictProxy[str] 110 """The response headers.""" 111 112 message: str 113 """A Bungie human readable message describes the cause of the error.""" 114 115 error_status: str 116 """A Bungie short error status describes the cause of the error.""" 117 118 message_data: dict[str, str] 119 """A dict of string key, value that includes each cause of the error 120 to a message describes information about that error. 121 """ 122 123 def __str__(self) -> str: 124 if self.message: 125 message_body = self.message 126 127 if self.error_status: 128 error_status_body = self.error_status 129 130 return ( 131 f"{self.http_status.name.replace('_', '').title()} {self.http_status.value}: " 132 f"Error status: {error_status_body}, Error message: {message_body} from {self.url} " 133 f"{str(self.body)}" 134 )
An in-depth HTTP exception that's raised with more information.
2def __init__(self, *, error_code, http_status, throttle_seconds, url, body, headers, message, error_status, message_data): 3 self.error_code = error_code 4 self.http_status = http_status 5 self.throttle_seconds = throttle_seconds 6 self.url = url 7 self.body = body 8 self.headers = headers 9 self.message = message 10 self.error_status = error_status 11 self.message_data = message_data 12 BaseException.__init__(self, self.error_code,self.http_status,self.throttle_seconds,self.url,self.body,self.headers,self.message,self.error_status,self.message_data)
Method generated by attrs for class HTTPException.
A dict of string key, value that includes each cause of the error to a message describes information about that error.
Inherited Members
- builtins.BaseException
- with_traceback
- args
71class Image: 72 """Representation of an image/avatar/picture at Bungie. 73 74 Example 75 ------- 76 ```py 77 from aiobungie import Image 78 img = Image("img/destiny_content/pgcr/raid_eclipse.jpg") 79 print(img) 80 # https://www.bungie.net/img/destiny_content/pgcr/raid_eclipse.jpg 81 82 # Stream the image. 83 async for chunk in img: 84 # Byte chunks of the image. 85 print(chunk) 86 87 # Save the image to a file. 88 await img.save("file_name", "/my/path/to/save/to", "jpeg") 89 ``` 90 91 Parameters 92 ---------- 93 path : `str | None` 94 The path to the image. If `None`, the default missing image path will be used. 95 """ 96 97 __slots__ = ("_path",) 98 99 def __init__(self, path: typing.Optional[str] = None) -> None: 100 self._path = path 101 102 @property 103 def is_missing(self) -> bool: 104 return not self._path 105 106 @property 107 def url(self) -> str: 108 """The URL to the image.""" 109 return self.create_url() 110 111 @staticmethod 112 def missing_path() -> str: 113 """Returns the path to the missing Bungie image.""" 114 return "img/misc/missing_icon_d2.png" 115 116 def create_url(self) -> str: 117 """Creates a full URL to the image path. 118 119 Returns 120 ------- 121 str 122 The URL to the image. 123 """ 124 return f"{url.BASE}/{self._path if self._path else self.missing_path()}" 125 126 async def save( 127 self, 128 file_name: str, 129 path: typing.Union[pathlib.Path, str], 130 /, 131 mime_type: typing.Optional[typing.Union[MimeType, str]] = None, 132 ) -> None: 133 """Saves the image to a file. 134 135 Parameters 136 ---------- 137 file_name : `str` 138 A name for the file to save the image to. 139 path : `pathlib.Path | str` 140 A path tp save the image to. 141 142 Other Parameters 143 ---------------- 144 mime_type : `MimeType | str` 145 Optional MIME type of the image. 146 147 Raises 148 ------ 149 `FileNotFoundError` 150 If the path provided does not exist. 151 `RuntimeError` 152 If the image could not be saved. 153 `PermissionError` 154 If the path provided is not writable or does not have write permissions. 155 """ 156 if isinstance(path, pathlib.Path) and not path.exists(): 157 raise FileNotFoundError(f"File does not exist: {path!r}") 158 159 if self.is_missing: 160 return 161 162 mimetype = mime_type or MimeType.PNG 163 path = pathlib.Path(path) 164 165 loop = helpers.get_or_make_loop() 166 pool = concurrent.futures.ThreadPoolExecutor() 167 168 try: 169 with pool: 170 await loop.run_in_executor( 171 pool, _write, path, file_name, mimetype, await self.read() 172 ) 173 _LOGGER.info("Saved image to %s", file_name) 174 175 except asyncio.CancelledError: 176 pass 177 178 except Exception as err: 179 raise RuntimeError("Encountered an error while saving image.") from err 180 181 async def read(self) -> bytes: 182 """Read this image bytes. 183 184 Returns 185 ------- 186 `bytes` 187 The bytes of this image. 188 """ 189 client_session = aiohttp.ClientSession() 190 191 try: 192 await client_session.__aenter__() 193 response = await client_session.get(self.create_url()) 194 195 if 300 >= response.status >= 200: 196 reader = await response.read() 197 198 except Exception as exc: 199 raise RuntimeError(f"Failed to read image: {exc}") from None 200 finally: 201 await client_session.__aexit__(None, None, None) 202 return reader 203 204 async def iter(self) -> collections.AsyncGenerator[bytes, None]: 205 """Iterates over the image bytes lazily. 206 207 Example 208 ------- 209 import aiobungie 210 211 resource = aiobungie.Image("img/misc/missing_icon_d2.png") 212 async for chunk in resource.iter(): 213 print(chunk) 214 215 Returns 216 ------- 217 `collections.AsyncGenerator[bytes, None]` 218 An async generator of the image bytes. 219 """ 220 221 async for chunk in self: 222 yield chunk 223 224 def __repr__(self) -> str: 225 return f"Image(url={self.create_url()})" 226 227 def __str__(self) -> str: 228 return self.create_url() 229 230 def __aiter__(self) -> Image: 231 return self 232 233 async def __anext__(self) -> bytes: 234 return await self.read() 235 236 def __await__(self) -> collections.Generator[None, None, bytes]: 237 return self.__anext__().__await__()
Representation of an image/avatar/picture at Bungie.
Example
from aiobungie import Image
img = Image("img/destiny_content/pgcr/raid_eclipse.jpg")
print(img)
# https://www.bungie.net/img/destiny_content/pgcr/raid_eclipse.jpg
# Stream the image.
async for chunk in img:
# Byte chunks of the image.
print(chunk)
# Save the image to a file.
await img.save("file_name", "/my/path/to/save/to", "jpeg")
Parameters
- path (
str | None): The path to the image. IfNone, the default missing image path will be used.
111 @staticmethod 112 def missing_path() -> str: 113 """Returns the path to the missing Bungie image.""" 114 return "img/misc/missing_icon_d2.png"
Returns the path to the missing Bungie image.
116 def create_url(self) -> str: 117 """Creates a full URL to the image path. 118 119 Returns 120 ------- 121 str 122 The URL to the image. 123 """ 124 return f"{url.BASE}/{self._path if self._path else self.missing_path()}"
Creates a full URL to the image path.
Returns
- str: The URL to the image.
126 async def save( 127 self, 128 file_name: str, 129 path: typing.Union[pathlib.Path, str], 130 /, 131 mime_type: typing.Optional[typing.Union[MimeType, str]] = None, 132 ) -> None: 133 """Saves the image to a file. 134 135 Parameters 136 ---------- 137 file_name : `str` 138 A name for the file to save the image to. 139 path : `pathlib.Path | str` 140 A path tp save the image to. 141 142 Other Parameters 143 ---------------- 144 mime_type : `MimeType | str` 145 Optional MIME type of the image. 146 147 Raises 148 ------ 149 `FileNotFoundError` 150 If the path provided does not exist. 151 `RuntimeError` 152 If the image could not be saved. 153 `PermissionError` 154 If the path provided is not writable or does not have write permissions. 155 """ 156 if isinstance(path, pathlib.Path) and not path.exists(): 157 raise FileNotFoundError(f"File does not exist: {path!r}") 158 159 if self.is_missing: 160 return 161 162 mimetype = mime_type or MimeType.PNG 163 path = pathlib.Path(path) 164 165 loop = helpers.get_or_make_loop() 166 pool = concurrent.futures.ThreadPoolExecutor() 167 168 try: 169 with pool: 170 await loop.run_in_executor( 171 pool, _write, path, file_name, mimetype, await self.read() 172 ) 173 _LOGGER.info("Saved image to %s", file_name) 174 175 except asyncio.CancelledError: 176 pass 177 178 except Exception as err: 179 raise RuntimeError("Encountered an error while saving image.") from err
Saves the image to a file.
Parameters
- file_name (
str): A name for the file to save the image to. - path (
pathlib.Path | str): A path tp save the image to.
Other Parameters
- mime_type (
MimeType | str): Optional MIME type of the image.
Raises
FileNotFoundError: If the path provided does not exist.RuntimeError: If the image could not be saved.PermissionError: If the path provided is not writable or does not have write permissions.
181 async def read(self) -> bytes: 182 """Read this image bytes. 183 184 Returns 185 ------- 186 `bytes` 187 The bytes of this image. 188 """ 189 client_session = aiohttp.ClientSession() 190 191 try: 192 await client_session.__aenter__() 193 response = await client_session.get(self.create_url()) 194 195 if 300 >= response.status >= 200: 196 reader = await response.read() 197 198 except Exception as exc: 199 raise RuntimeError(f"Failed to read image: {exc}") from None 200 finally: 201 await client_session.__aexit__(None, None, None) 202 return reader
Read this image bytes.
Returns
bytes: The bytes of this image.
204 async def iter(self) -> collections.AsyncGenerator[bytes, None]: 205 """Iterates over the image bytes lazily. 206 207 Example 208 ------- 209 import aiobungie 210 211 resource = aiobungie.Image("img/misc/missing_icon_d2.png") 212 async for chunk in resource.iter(): 213 print(chunk) 214 215 Returns 216 ------- 217 `collections.AsyncGenerator[bytes, None]` 218 An async generator of the image bytes. 219 """ 220 221 async for chunk in self: 222 yield chunk
Iterates over the image bytes lazily.
Example
import aiobungie
resource = aiobungie.Image("img/misc/missing_icon_d2.png") async for chunk in resource.iter(): print(chunk)
Returns
collections.AsyncGenerator[bytes, None]: An async generator of the image bytes.
243@attrs.define(auto_exc=True) 244class InternalServerError(HTTPException): 245 """Raised for 5xx internal server errors."""
Raised for 5xx internal server errors.
2def __init__(self, *, error_code, http_status, throttle_seconds, url, body, headers, message, error_status, message_data): 3 self.error_code = error_code 4 self.http_status = http_status 5 self.throttle_seconds = throttle_seconds 6 self.url = url 7 self.body = body 8 self.headers = headers 9 self.message = message 10 self.error_status = error_status 11 self.message_data = message_data 12 BaseException.__init__(self, self.error_code,self.http_status,self.throttle_seconds,self.url,self.body,self.headers,self.message,self.error_status,self.message_data)
Method generated by attrs for class InternalServerError.
Inherited Members
- HTTPException
- error_code
- http_status
- throttle_seconds
- url
- body
- headers
- message
- error_status
- message_data
- builtins.BaseException
- with_traceback
- args
711@typing.final 712class ItemBindStatus(int, Enum): 713 """An enum for Destiny 2 items bind status.""" 714 715 NOT_BOUND = 0 716 BOUND_TO_CHARACTER = 1 717 BOUND_TO_ACCOUNT = 2 718 BOUNT_TO_GUILD = 3
An enum for Destiny 2 items bind status.
721@typing.final 722class ItemLocation(int, Enum): 723 """An enum for Destiny 2 items location.""" 724 725 UNKNOWN = 0 726 INVENTORY = 1 727 VAULT = 2 728 VENDOR = 3 729 POSTMASTER = 4
An enum for Destiny 2 items location.
746@typing.final 747class ItemState(Flag): 748 """An enum for Destiny 2 item states.""" 749 750 NONE = 0 751 LOCKED = 1 << 0 752 TRACKED = 1 << 1 753 MASTERWORKED = 1 << 2 754 CRAFTED = 1 << 3 755 """If this bit is set, the item has been 'crafted' by the player.""" 756 HIGHLITED_OBJECTIVE = 1 << 4 757 """If this bit is set, the item is a 'highlighted' objective."""
An enum for Destiny 2 item states.
If this bit is set, the item is a 'highlighted' objective.
578@typing.final 579class ItemSubType(int, Enum): 580 """An enum for Destiny 2 inventory items subtype.""" 581 582 NONE = 0 583 AUTORIFLE = 6 584 SHOTGUN = 7 585 MACHINEGUN = 8 586 HANDCANNON = 9 587 ROCKETLAUNCHER = 10 588 FUSIONRIFLE = 11 589 SNIPERRIFLE = 12 590 PULSERIFLE = 13 591 SCOUTRIFLE = 14 592 SIDEARM = 17 593 SWORD = 18 594 MASK = 19 595 SHADER = 20 596 ORNAMENT = 21 597 FUSIONRIFLELINE = 22 598 GRENADELAUNCHER = 23 599 SUBMACHINEGUN = 24 600 TRACERIFLE = 25 601 HELMETARMOR = 26 602 GAUNTLETSARMOR = 27 603 CHESTARMOR = 28 604 LEGARMOR = 29 605 CLASSARMOR = 30 606 BOW = 31 607 DUMMYREPEATABLEBOUNTY = 32
An enum for Destiny 2 inventory items subtype.
610@typing.final 611class ItemTier(int, Enum): 612 """An enum for a Destiny 2 item tier.""" 613 614 NONE = 0 615 BASIC = 3340296461 616 COMMON = 2395677314 617 RARE = 2127292149 618 LEGENDERY = 4008398120 619 EXOTIC = 2759499571
An enum for a Destiny 2 item tier.
545@typing.final 546class ItemType(int, Enum): 547 """Enums for Destiny2's item types.""" 548 549 NONE = 0 550 CURRENCY = 1 551 ARMOR = 2 552 WEAPON = 3 553 MESSAGE = 7 554 ENGRAM = 8 555 CONSUMABLE = 9 556 EXCHANGEMATERIAL = 10 557 MISSIONREWARD = 11 558 QUESTSTEP = 12 559 QUESTSTEPCOMPLETE = 13 560 EMBLEM = 14 561 QUEST = 15 562 SUBCLASS = 16 563 CLANBANNER = 17 564 AURA = 18 565 MOD = 19 566 DUMMY = 20 567 SHIP = 21 568 VEHICLE = 22 569 EMOTE = 23 570 GHOST = 24 571 PACKAGE = 25 572 BOUNTY = 26 573 WRAPPER = 27 574 SEASONALARTIFACT = 28 575 FINISHER = 29
Enums for Destiny2's item types.
45class Iterator(typing.Generic[Item]): 46 """A Flat, In-Memory iterator for sequenced based data. 47 48 Example 49 ------- 50 ```py 51 iterator = Iterator([1, 2, 3]) 52 53 # Map the results. 54 for item in iterator.map(lambda item: item * 2): 55 print(item) 56 # 2 57 # 4 58 59 # Indexing is also supported. 60 print(iterator[0]) 61 # 1 62 63 # Normal iteration. 64 for item in iterator: 65 print(item) 66 # 1 67 # 2 68 # 3 69 70 # Union two iterators. 71 iterator2 = Iterator([4, 5, 6]) 72 final = iterator | iterator2 73 # <Iterator([1, 2, 3, 4, 5, 6])> 74 ``` 75 76 Parameters 77 ---------- 78 items: `collections.Iterable[Item]` 79 The items to iterate over. 80 """ 81 82 __slots__ = ("_items",) 83 84 def __init__(self, items: collections.Iterable[Item]) -> None: 85 self._items = iter(items) 86 87 @typing.overload 88 def collect(self) -> list[Item]: 89 ... 90 91 @typing.overload 92 def collect(self, casting: _B) -> list[_B]: 93 ... 94 95 def collect( 96 self, casting: typing.Optional[_B] = None 97 ) -> typing.Union[list[Item], list[_B]]: 98 """Collects all items in the iterator into a list and cast them into an object if provided. 99 100 Example 101 ------- 102 >>> iterator = Iterator([1, 2, 3]) 103 >>> iterator.collect(casting=str) 104 ["1", "2", "3"] 105 106 Parameters 107 ---------- 108 casting: `T | None` 109 The type to cast the items to. If `None` is provided, the items will be returned as is. 110 111 Raises 112 ------ 113 `StopIteration` 114 If no elements are left in the iterator. 115 """ 116 if casting is not None: 117 return typing.cast(list[_B], list(map(casting, self._items))) 118 119 return list(self._items) 120 121 def next(self) -> Item: 122 """Returns the next item in the iterator. 123 124 Example 125 ------- 126 ```py 127 iterator = Iterator(["1", "2", "3"]) 128 item = iterator.next() 129 assert item == "1" 130 item = iterator.next() 131 assert item == "2" 132 ``` 133 134 Raises 135 ------ 136 `StopIteration` 137 If no elements are left in the iterator. 138 """ 139 try: 140 return self.__next__() 141 except StopIteration: 142 self._ok() 143 144 def map( 145 self, predicate: collections.Callable[[Item], OtherItem] 146 ) -> Iterator[OtherItem]: 147 """Maps each item in the iterator to its predicated value. 148 149 Example 150 ------- 151 ```py 152 iterator = Iterator(["1", "2", "3"]).map(lambda value: int(value)) 153 print(iterator) 154 # <Iterator([1, 2, 3])> 155 ``` 156 157 Parameters 158 ---------- 159 predicate: `collections.Callable[[Item], OtherItem]` 160 The function to map each item in the iterator to its predicated value. 161 162 Returns 163 ------- 164 `Iterator[OtherItem]` 165 The mapped iterator. 166 167 Raises 168 ------ 169 `StopIteration` 170 If no elements are left in the iterator. 171 """ 172 return Iterator(map(predicate, self._items)) 173 174 def take(self, n: int) -> Iterator[Item]: 175 """Take the first number of items until the number of items are yielded or 176 the end of the iterator is reached. 177 178 Example 179 ------- 180 ```py 181 iterator = Iterator([GameMode.RAID, GameMode.STRIKE, GameMode.GAMBIT]) 182 print(iterator.take(2)) 183 # <Iterator([GameMode.RAID, GameMode.STRIKE])> 184 ``` 185 186 Parameters 187 ---------- 188 n: `int` 189 The number of items to take. 190 191 Raises 192 ------ 193 `StopIteration` 194 If no elements are left in the iterator. 195 """ 196 return Iterator(itertools.islice(self._items, n)) 197 198 def take_while( 199 self, predicate: collections.Callable[[Item], bool] 200 ) -> Iterator[Item]: 201 """Yields items from the iterator while predicate returns `True`. 202 203 Example 204 ------- 205 ```py 206 iterator = Iterator([STEAM, XBOX, STADIA]) 207 print(iterator.take_while(lambda platform: platform is not XBOX)) 208 # <Iterator([STEAM])> 209 ``` 210 211 Parameters 212 ---------- 213 predicate: `collections.Callable[[Item], bool]` 214 The function to predicate each item in the iterator. 215 216 Raises 217 ------ 218 `StopIteration` 219 If no elements are left in the iterator. 220 """ 221 return Iterator(itertools.takewhile(predicate, self._items)) 222 223 def drop_while( 224 self, predicate: collections.Callable[[Item], bool] 225 ) -> Iterator[Item]: 226 """Yields items from the iterator while predicate returns `False`. 227 228 Example 229 ------- 230 ```py 231 iterator = Iterator([DestinyMembership(name="Jim"), DestinyMembership(name="Bob")]) 232 print(iterator.drop_while(lambda membership: membership.name is not "Jim")) 233 # <Iterator([DestinyMembership(name="Bob")])> 234 ``` 235 236 Parameters 237 ---------- 238 predicate: `collections.Callable[[Item], bool]` 239 The function to predicate each item in the iterator. 240 241 Raises 242 ------ 243 `StopIteration` 244 If no elements are left in the iterator. 245 """ 246 return Iterator(itertools.dropwhile(predicate, self._items)) 247 248 def filter(self, predicate: collections.Callable[[Item], bool]) -> Iterator[Item]: 249 """Filters the iterator to only yield items that match the predicate. 250 251 Example 252 ------- 253 ```py 254 names = Iterator(["Jim", "Bob", "Mike", "Jess"]) 255 print(names.filter(lambda n: n != "Jim")) 256 # <Iterator(["Bob", "Mike", "Jess"])> 257 ``` 258 """ 259 return Iterator(filter(predicate, self._items)) 260 261 def skip(self, n: int) -> Iterator[Item]: 262 """Skips the first number of items in the iterator. 263 264 Example 265 ------- 266 ```py 267 iterator = Iterator([STEAM, XBOX, STADIA]) 268 print(iterator.skip(1)) 269 # <Iterator([XBOX, STADIA])> 270 ``` 271 """ 272 return Iterator(itertools.islice(self._items, n, None)) 273 274 def zip(self, other: Iterator[OtherItem]) -> Iterator[tuple[Item, OtherItem]]: 275 """Zips the iterator with another iterable. 276 277 Example 278 ------- 279 ```py 280 iterator = Iterator([1, 3, 5]) 281 other = Iterator([2, 4, 6]) 282 for item, other_item in iterator.zip(other): 283 print(item, other_item) 284 # <Iterator([(1, 2), (3, 4), (5, 6)])> 285 ``` 286 287 Parameters 288 ---------- 289 other: `Iterator[OtherItem]` 290 The iterable to zip with. 291 292 Raises 293 ------ 294 `StopIteration` 295 If no elements are left in the iterator. 296 """ 297 return Iterator(zip(self._items, other)) 298 299 def all(self, predicate: collections.Callable[[Item], bool]) -> bool: 300 """`True` if all items in the iterator match the predicate. 301 302 Example 303 ------- 304 ```py 305 iterator = Iterator([1, 2, 3]) 306 while iterator.all(lambda item: isinstance(item, int)): 307 print("Still all integers") 308 continue 309 # Still all integers 310 ``` 311 312 Parameters 313 ---------- 314 predicate: `collections.Callable[[Item], bool]` 315 The function to test each item in the iterator. 316 317 Raises 318 ------ 319 `StopIteration` 320 If no elements are left in the iterator. 321 """ 322 return all(predicate(item) for item in self) 323 324 def any(self, predicate: collections.Callable[[Item], bool]) -> bool: 325 """`True` if any items in the iterator match the predicate. 326 327 Example 328 ------- 329 ```py 330 iterator = Iterator([1, 2, 3]) 331 if iterator.any(lambda item: isinstance(item, int)): 332 print("At least one item is an int.") 333 # At least one item is an int. 334 ``` 335 336 Parameters 337 ---------- 338 predicate: `collections.Callable[[Item], bool]` 339 The function to test each item in the iterator. 340 341 Raises 342 ------ 343 `StopIteration` 344 If no elements are left in the iterator. 345 """ 346 return any(predicate(item) for item in self) 347 348 def sort( 349 self, 350 *, 351 key: collections.Callable[[Item], typeshed.SupportsRichComparison], 352 reverse: bool = False, 353 ) -> Iterator[Item]: 354 """Sorts the iterator. 355 356 Example 357 ------- 358 ```py 359 iterator = Iterator([3, 1, 6, 7]) 360 print(iterator.sort(key=lambda item: item)) 361 # <Iterator([1, 3, 6, 7])> 362 ``` 363 364 Parameters 365 ---------- 366 key: `collections.Callable[[Item], Any]` 367 The function to sort by. 368 reverse: `bool` 369 Whether to reverse the sort. 370 371 Raises 372 ------ 373 `StopIteration` 374 If no elements are left in the iterator. 375 """ 376 return Iterator(sorted(self._items, key=key, reverse=reverse)) 377 378 def first(self) -> Item: 379 """Returns the first item in the iterator. 380 381 Example 382 ------- 383 ```py 384 iterator = Iterator([3, 1, 6, 7]) 385 print(iterator.first()) 386 3 387 ``` 388 389 Raises 390 ------ 391 `StopIteration` 392 If no elements are left in the iterator. 393 """ 394 return self.take(1).next() 395 396 def reversed(self) -> Iterator[Item]: 397 """Returns a new iterator that yields the items in the iterator in reverse order. 398 399 Example 400 ------- 401 ```py 402 iterator = Iterator([3, 1, 6, 7]) 403 print(iterator.reversed()) 404 # <Iterator([7, 6, 1, 3])> 405 ``` 406 407 Raises 408 ------ 409 `StopIteration` 410 If no elements are left in the iterator. 411 """ 412 return Iterator(reversed(self.collect())) 413 414 def count(self) -> int: 415 """Returns the number of items in the iterator. 416 417 Example 418 ------- 419 ```py 420 iterator = Iterator([3, 1, 6, 7]) 421 print(iterator.count()) 422 4 423 ``` 424 """ 425 count = 0 426 for _ in self: 427 count += 1 428 429 return count 430 431 def union(self, other: Iterator[Item]) -> Iterator[Item]: 432 """Returns a new iterator that yields all items from both iterators. 433 434 Example 435 ------- 436 ```py 437 iterator = Iterator([1, 2, 3]) 438 other = Iterator([4, 5, 6]) 439 print(iterator.union(other)) 440 # <Iterator([1, 2, 3, 4, 5, 6])> 441 ``` 442 443 Parameters 444 ---------- 445 other: `Iterator[Item]` 446 The iterable to union with. 447 448 Raises 449 ------ 450 `StopIteration` 451 If no elements are left in the iterator. 452 """ 453 return Iterator(itertools.chain(self._items, other)) 454 455 def for_each(self, func: collections.Callable[[Item], typing.Any]) -> None: 456 """Calls the function on each item in the iterator. 457 458 Example 459 ------- 460 ```py 461 iterator = Iterator([1, 2, 3]) 462 iterator.for_each(lambda item: print(item)) 463 # 1 464 # 2 465 # 3 466 ``` 467 468 Parameters 469 ---------- 470 func: `typeshed.Callable[[Item], None]` 471 The function to call on each item in the iterator. 472 """ 473 for item in self: 474 func(item) 475 476 async def async_for_each( 477 self, 478 func: collections.Callable[[Item], collections.Coroutine[None, None, None]], 479 ) -> None: 480 """Calls the async function on each item in the iterator concurrently. 481 482 Example 483 ------- 484 ```py 485 async def signup(username: str) -> None: 486 async with aiohttp.request('POST', '...') as r: 487 # Actual logic. 488 ... 489 490 async def main(): 491 users = aiobungie.into_iter(["user_danny", "user_jojo"]) 492 await users.async_for_each(lambda username: signup(username)) 493 ``` 494 495 Parameters 496 ---------- 497 func: `collections.Callable[[Item], collections.Coroutine[None, None, None]]` 498 The async function to call on each item in the iterator. 499 """ 500 await _helpers.awaits(*(func(item) for item in self)) 501 502 def enumerate(self, *, start: int = 0) -> Iterator[tuple[int, Item]]: 503 """Returns a new iterator that yields tuples of the index and item. 504 505 Example 506 ------- 507 ```py 508 iterator = Iterator([1, 2, 3]) 509 for index, item in iterator.enumerate(): 510 print(index, item) 511 # 0 1 512 # 1 2 513 # 2 3 514 ``` 515 516 Raises 517 ------ 518 `StopIteration` 519 If no elements are left in the iterator. 520 """ 521 return Iterator(enumerate(self._items, start=start)) 522 523 def _ok(self) -> typing.NoReturn: 524 raise StopIteration("No more items in the iterator.") from None 525 526 def __getitem__(self, index: int) -> Item: 527 try: 528 return self.skip(index).first() 529 except IndexError: 530 self._ok() 531 532 def __or__(self, other: Iterator[Item]) -> Iterator[Item]: 533 return self.union(other) 534 535 # This is a never. 536 def __setitem__(self) -> typing.NoReturn: 537 raise TypeError( 538 f"{type(self).__name__} doesn't support item assignment." 539 ) from None 540 541 def __repr__(self) -> str: 542 return f'<{self.__class__.__name__}({", ".join([str(item) for item in self])})>' 543 544 def __len__(self) -> int: 545 return self.count() 546 547 def __iter__(self) -> Iterator[Item]: 548 return self 549 550 def __next__(self) -> Item: 551 try: 552 item = next(self._items) 553 except StopIteration: 554 self._ok() 555 556 return item
A Flat, In-Memory iterator for sequenced based data.
Example
iterator = Iterator([1, 2, 3])
# Map the results.
for item in iterator.map(lambda item: item * 2):
print(item)
# 2
# 4
# Indexing is also supported.
print(iterator[0])
# 1
# Normal iteration.
for item in iterator:
print(item)
# 1
# 2
# 3
# Union two iterators.
iterator2 = Iterator([4, 5, 6])
final = iterator | iterator2
# <Iterator([1, 2, 3, 4, 5, 6])>
Parameters
- items (
collections.Iterable[Item]): The items to iterate over.
95 def collect( 96 self, casting: typing.Optional[_B] = None 97 ) -> typing.Union[list[Item], list[_B]]: 98 """Collects all items in the iterator into a list and cast them into an object if provided. 99 100 Example 101 ------- 102 >>> iterator = Iterator([1, 2, 3]) 103 >>> iterator.collect(casting=str) 104 ["1", "2", "3"] 105 106 Parameters 107 ---------- 108 casting: `T | None` 109 The type to cast the items to. If `None` is provided, the items will be returned as is. 110 111 Raises 112 ------ 113 `StopIteration` 114 If no elements are left in the iterator. 115 """ 116 if casting is not None: 117 return typing.cast(list[_B], list(map(casting, self._items))) 118 119 return list(self._items)
Collects all items in the iterator into a list and cast them into an object if provided.
Example
>>> iterator = Iterator([1, 2, 3])
>>> iterator.collect(casting=str)
["1", "2", "3"]
Parameters
- casting (
T | None): The type to cast the items to. IfNoneis provided, the items will be returned as is.
Raises
StopIteration: If no elements are left in the iterator.
121 def next(self) -> Item: 122 """Returns the next item in the iterator. 123 124 Example 125 ------- 126 ```py 127 iterator = Iterator(["1", "2", "3"]) 128 item = iterator.next() 129 assert item == "1" 130 item = iterator.next() 131 assert item == "2" 132 ``` 133 134 Raises 135 ------ 136 `StopIteration` 137 If no elements are left in the iterator. 138 """ 139 try: 140 return self.__next__() 141 except StopIteration: 142 self._ok()
Returns the next item in the iterator.
Example
iterator = Iterator(["1", "2", "3"])
item = iterator.next()
assert item == "1"
item = iterator.next()
assert item == "2"
Raises
StopIteration: If no elements are left in the iterator.
144 def map( 145 self, predicate: collections.Callable[[Item], OtherItem] 146 ) -> Iterator[OtherItem]: 147 """Maps each item in the iterator to its predicated value. 148 149 Example 150 ------- 151 ```py 152 iterator = Iterator(["1", "2", "3"]).map(lambda value: int(value)) 153 print(iterator) 154 # <Iterator([1, 2, 3])> 155 ``` 156 157 Parameters 158 ---------- 159 predicate: `collections.Callable[[Item], OtherItem]` 160 The function to map each item in the iterator to its predicated value. 161 162 Returns 163 ------- 164 `Iterator[OtherItem]` 165 The mapped iterator. 166 167 Raises 168 ------ 169 `StopIteration` 170 If no elements are left in the iterator. 171 """ 172 return Iterator(map(predicate, self._items))
Maps each item in the iterator to its predicated value.
Example
iterator = Iterator(["1", "2", "3"]).map(lambda value: int(value))
print(iterator)
# <Iterator([1, 2, 3])>
Parameters
- predicate (
collections.Callable[[Item], OtherItem]): The function to map each item in the iterator to its predicated value.
Returns
Iterator[OtherItem]: The mapped iterator.
Raises
StopIteration: If no elements are left in the iterator.
174 def take(self, n: int) -> Iterator[Item]: 175 """Take the first number of items until the number of items are yielded or 176 the end of the iterator is reached. 177 178 Example 179 ------- 180 ```py 181 iterator = Iterator([GameMode.RAID, GameMode.STRIKE, GameMode.GAMBIT]) 182 print(iterator.take(2)) 183 # <Iterator([GameMode.RAID, GameMode.STRIKE])> 184 ``` 185 186 Parameters 187 ---------- 188 n: `int` 189 The number of items to take. 190 191 Raises 192 ------ 193 `StopIteration` 194 If no elements are left in the iterator. 195 """ 196 return Iterator(itertools.islice(self._items, n))
Take the first number of items until the number of items are yielded or the end of the iterator is reached.
Example
iterator = Iterator([GameMode.RAID, GameMode.STRIKE, GameMode.GAMBIT])
print(iterator.take(2))
# <Iterator([GameMode.RAID, GameMode.STRIKE])>
Parameters
- n (
int): The number of items to take.
Raises
StopIteration: If no elements are left in the iterator.
198 def take_while( 199 self, predicate: collections.Callable[[Item], bool] 200 ) -> Iterator[Item]: 201 """Yields items from the iterator while predicate returns `True`. 202 203 Example 204 ------- 205 ```py 206 iterator = Iterator([STEAM, XBOX, STADIA]) 207 print(iterator.take_while(lambda platform: platform is not XBOX)) 208 # <Iterator([STEAM])> 209 ``` 210 211 Parameters 212 ---------- 213 predicate: `collections.Callable[[Item], bool]` 214 The function to predicate each item in the iterator. 215 216 Raises 217 ------ 218 `StopIteration` 219 If no elements are left in the iterator. 220 """ 221 return Iterator(itertools.takewhile(predicate, self._items))
Yields items from the iterator while predicate returns True.
Example
iterator = Iterator([STEAM, XBOX, STADIA])
print(iterator.take_while(lambda platform: platform is not XBOX))
# <Iterator([STEAM])>
Parameters
- predicate (
collections.Callable[[Item], bool]): The function to predicate each item in the iterator.
Raises
StopIteration: If no elements are left in the iterator.
223 def drop_while( 224 self, predicate: collections.Callable[[Item], bool] 225 ) -> Iterator[Item]: 226 """Yields items from the iterator while predicate returns `False`. 227 228 Example 229 ------- 230 ```py 231 iterator = Iterator([DestinyMembership(name="Jim"), DestinyMembership(name="Bob")]) 232 print(iterator.drop_while(lambda membership: membership.name is not "Jim")) 233 # <Iterator([DestinyMembership(name="Bob")])> 234 ``` 235 236 Parameters 237 ---------- 238 predicate: `collections.Callable[[Item], bool]` 239 The function to predicate each item in the iterator. 240 241 Raises 242 ------ 243 `StopIteration` 244 If no elements are left in the iterator. 245 """ 246 return Iterator(itertools.dropwhile(predicate, self._items))
Yields items from the iterator while predicate returns False.
Example
iterator = Iterator([DestinyMembership(name="Jim"), DestinyMembership(name="Bob")])
print(iterator.drop_while(lambda membership: membership.name is not "Jim"))
# <Iterator([DestinyMembership(name="Bob")])>
Parameters
- predicate (
collections.Callable[[Item], bool]): The function to predicate each item in the iterator.
Raises
StopIteration: If no elements are left in the iterator.
248 def filter(self, predicate: collections.Callable[[Item], bool]) -> Iterator[Item]: 249 """Filters the iterator to only yield items that match the predicate. 250 251 Example 252 ------- 253 ```py 254 names = Iterator(["Jim", "Bob", "Mike", "Jess"]) 255 print(names.filter(lambda n: n != "Jim")) 256 # <Iterator(["Bob", "Mike", "Jess"])> 257 ``` 258 """ 259 return Iterator(filter(predicate, self._items))
Filters the iterator to only yield items that match the predicate.
Example
names = Iterator(["Jim", "Bob", "Mike", "Jess"])
print(names.filter(lambda n: n != "Jim"))
# <Iterator(["Bob", "Mike", "Jess"])>
261 def skip(self, n: int) -> Iterator[Item]: 262 """Skips the first number of items in the iterator. 263 264 Example 265 ------- 266 ```py 267 iterator = Iterator([STEAM, XBOX, STADIA]) 268 print(iterator.skip(1)) 269 # <Iterator([XBOX, STADIA])> 270 ``` 271 """ 272 return Iterator(itertools.islice(self._items, n, None))
Skips the first number of items in the iterator.
Example
iterator = Iterator([STEAM, XBOX, STADIA])
print(iterator.skip(1))
# <Iterator([XBOX, STADIA])>
274 def zip(self, other: Iterator[OtherItem]) -> Iterator[tuple[Item, OtherItem]]: 275 """Zips the iterator with another iterable. 276 277 Example 278 ------- 279 ```py 280 iterator = Iterator([1, 3, 5]) 281 other = Iterator([2, 4, 6]) 282 for item, other_item in iterator.zip(other): 283 print(item, other_item) 284 # <Iterator([(1, 2), (3, 4), (5, 6)])> 285 ``` 286 287 Parameters 288 ---------- 289 other: `Iterator[OtherItem]` 290 The iterable to zip with. 291 292 Raises 293 ------ 294 `StopIteration` 295 If no elements are left in the iterator. 296 """ 297 return Iterator(zip(self._items, other))
Zips the iterator with another iterable.
Example
iterator = Iterator([1, 3, 5])
other = Iterator([2, 4, 6])
for item, other_item in iterator.zip(other):
print(item, other_item)
# <Iterator([(1, 2), (3, 4), (5, 6)])>
Parameters
- other (
Iterator[OtherItem]): The iterable to zip with.
Raises
StopIteration: If no elements are left in the iterator.
299 def all(self, predicate: collections.Callable[[Item], bool]) -> bool: 300 """`True` if all items in the iterator match the predicate. 301 302 Example 303 ------- 304 ```py 305 iterator = Iterator([1, 2, 3]) 306 while iterator.all(lambda item: isinstance(item, int)): 307 print("Still all integers") 308 continue 309 # Still all integers 310 ``` 311 312 Parameters 313 ---------- 314 predicate: `collections.Callable[[Item], bool]` 315 The function to test each item in the iterator. 316 317 Raises 318 ------ 319 `StopIteration` 320 If no elements are left in the iterator. 321 """ 322 return all(predicate(item) for item in self)
True if all items in the iterator match the predicate.
Example
iterator = Iterator([1, 2, 3])
while iterator.all(lambda item: isinstance(item, int)):
print("Still all integers")
continue
# Still all integers
Parameters
- predicate (
collections.Callable[[Item], bool]): The function to test each item in the iterator.
Raises
StopIteration: If no elements are left in the iterator.
324 def any(self, predicate: collections.Callable[[Item], bool]) -> bool: 325 """`True` if any items in the iterator match the predicate. 326 327 Example 328 ------- 329 ```py 330 iterator = Iterator([1, 2, 3]) 331 if iterator.any(lambda item: isinstance(item, int)): 332 print("At least one item is an int.") 333 # At least one item is an int. 334 ``` 335 336 Parameters 337 ---------- 338 predicate: `collections.Callable[[Item], bool]` 339 The function to test each item in the iterator. 340 341 Raises 342 ------ 343 `StopIteration` 344 If no elements are left in the iterator. 345 """ 346 return any(predicate(item) for item in self)
True if any items in the iterator match the predicate.
Example
iterator = Iterator([1, 2, 3])
if iterator.any(lambda item: isinstance(item, int)):
print("At least one item is an int.")
# At least one item is an int.
Parameters
- predicate (
collections.Callable[[Item], bool]): The function to test each item in the iterator.
Raises
StopIteration: If no elements are left in the iterator.
348 def sort( 349 self, 350 *, 351 key: collections.Callable[[Item], typeshed.SupportsRichComparison], 352 reverse: bool = False, 353 ) -> Iterator[Item]: 354 """Sorts the iterator. 355 356 Example 357 ------- 358 ```py 359 iterator = Iterator([3, 1, 6, 7]) 360 print(iterator.sort(key=lambda item: item)) 361 # <Iterator([1, 3, 6, 7])> 362 ``` 363 364 Parameters 365 ---------- 366 key: `collections.Callable[[Item], Any]` 367 The function to sort by. 368 reverse: `bool` 369 Whether to reverse the sort. 370 371 Raises 372 ------ 373 `StopIteration` 374 If no elements are left in the iterator. 375 """ 376 return Iterator(sorted(self._items, key=key, reverse=reverse))
Sorts the iterator.
Example
iterator = Iterator([3, 1, 6, 7])
print(iterator.sort(key=lambda item: item))
# <Iterator([1, 3, 6, 7])>
Parameters
- key (
collections.Callable[[Item], Any]): The function to sort by. - reverse (
bool): Whether to reverse the sort.
Raises
StopIteration: If no elements are left in the iterator.
378 def first(self) -> Item: 379 """Returns the first item in the iterator. 380 381 Example 382 ------- 383 ```py 384 iterator = Iterator([3, 1, 6, 7]) 385 print(iterator.first()) 386 3 387 ``` 388 389 Raises 390 ------ 391 `StopIteration` 392 If no elements are left in the iterator. 393 """ 394 return self.take(1).next()
Returns the first item in the iterator.
Example
iterator = Iterator([3, 1, 6, 7])
print(iterator.first())
3
Raises
StopIteration: If no elements are left in the iterator.
396 def reversed(self) -> Iterator[Item]: 397 """Returns a new iterator that yields the items in the iterator in reverse order. 398 399 Example 400 ------- 401 ```py 402 iterator = Iterator([3, 1, 6, 7]) 403 print(iterator.reversed()) 404 # <Iterator([7, 6, 1, 3])> 405 ``` 406 407 Raises 408 ------ 409 `StopIteration` 410 If no elements are left in the iterator. 411 """ 412 return Iterator(reversed(self.collect()))
Returns a new iterator that yields the items in the iterator in reverse order.
Example
iterator = Iterator([3, 1, 6, 7])
print(iterator.reversed())
# <Iterator([7, 6, 1, 3])>
Raises
StopIteration: If no elements are left in the iterator.
414 def count(self) -> int: 415 """Returns the number of items in the iterator. 416 417 Example 418 ------- 419 ```py 420 iterator = Iterator([3, 1, 6, 7]) 421 print(iterator.count()) 422 4 423 ``` 424 """ 425 count = 0 426 for _ in self: 427 count += 1 428 429 return count
Returns the number of items in the iterator.
Example
iterator = Iterator([3, 1, 6, 7])
print(iterator.count())
4
431 def union(self, other: Iterator[Item]) -> Iterator[Item]: 432 """Returns a new iterator that yields all items from both iterators. 433 434 Example 435 ------- 436 ```py 437 iterator = Iterator([1, 2, 3]) 438 other = Iterator([4, 5, 6]) 439 print(iterator.union(other)) 440 # <Iterator([1, 2, 3, 4, 5, 6])> 441 ``` 442 443 Parameters 444 ---------- 445 other: `Iterator[Item]` 446 The iterable to union with. 447 448 Raises 449 ------ 450 `StopIteration` 451 If no elements are left in the iterator. 452 """ 453 return Iterator(itertools.chain(self._items, other))
Returns a new iterator that yields all items from both iterators.
Example
iterator = Iterator([1, 2, 3])
other = Iterator([4, 5, 6])
print(iterator.union(other))
# <Iterator([1, 2, 3, 4, 5, 6])>
Parameters
- other (
Iterator[Item]): The iterable to union with.
Raises
StopIteration: If no elements are left in the iterator.
455 def for_each(self, func: collections.Callable[[Item], typing.Any]) -> None: 456 """Calls the function on each item in the iterator. 457 458 Example 459 ------- 460 ```py 461 iterator = Iterator([1, 2, 3]) 462 iterator.for_each(lambda item: print(item)) 463 # 1 464 # 2 465 # 3 466 ``` 467 468 Parameters 469 ---------- 470 func: `typeshed.Callable[[Item], None]` 471 The function to call on each item in the iterator. 472 """ 473 for item in self: 474 func(item)
Calls the function on each item in the iterator.
Example
iterator = Iterator([1, 2, 3])
iterator.for_each(lambda item: print(item))
# 1
# 2
# 3
Parameters
- func (
typeshed.Callable[[Item], None]): The function to call on each item in the iterator.
476 async def async_for_each( 477 self, 478 func: collections.Callable[[Item], collections.Coroutine[None, None, None]], 479 ) -> None: 480 """Calls the async function on each item in the iterator concurrently. 481 482 Example 483 ------- 484 ```py 485 async def signup(username: str) -> None: 486 async with aiohttp.request('POST', '...') as r: 487 # Actual logic. 488 ... 489 490 async def main(): 491 users = aiobungie.into_iter(["user_danny", "user_jojo"]) 492 await users.async_for_each(lambda username: signup(username)) 493 ``` 494 495 Parameters 496 ---------- 497 func: `collections.Callable[[Item], collections.Coroutine[None, None, None]]` 498 The async function to call on each item in the iterator. 499 """ 500 await _helpers.awaits(*(func(item) for item in self))
Calls the async function on each item in the iterator concurrently.
Example
async def signup(username: str) -> None:
async with aiohttp.request('POST', '...') as r:
# Actual logic.
...
async def main():
users = aiobungie.into_iter(["user_danny", "user_jojo"])
await users.async_for_each(lambda username: signup(username))
Parameters
- func (
collections.Callable[[Item], collections.Coroutine[None, None, None]]): The async function to call on each item in the iterator.
502 def enumerate(self, *, start: int = 0) -> Iterator[tuple[int, Item]]: 503 """Returns a new iterator that yields tuples of the index and item. 504 505 Example 506 ------- 507 ```py 508 iterator = Iterator([1, 2, 3]) 509 for index, item in iterator.enumerate(): 510 print(index, item) 511 # 0 1 512 # 1 2 513 # 2 3 514 ``` 515 516 Raises 517 ------ 518 `StopIteration` 519 If no elements are left in the iterator. 520 """ 521 return Iterator(enumerate(self._items, start=start))
Returns a new iterator that yields tuples of the index and item.
Example
iterator = Iterator([1, 2, 3])
for index, item in iterator.enumerate():
print(index, item)
# 0 1
# 1 2
# 2 3
Raises
StopIteration: If no elements are left in the iterator.
702@typing.final 703class MembershipOption(int, Enum): 704 """A enum for GroupV2 membership options.""" 705 706 REVIEWD = 0 707 OPEN = 1 708 CLOSED = 2
A enum for GroupV2 membership options.
450@typing.final 451class MembershipType(int, Enum): 452 """An Enum for Bungie membership types.""" 453 454 NONE = 0 455 XBOX = 1 456 PSN = 2 457 STEAM = 3 458 BLIZZARD = 4 459 STADIA = 5 460 EPIC_GAMES_STORE = 6 461 DEMON = 10 462 BUNGIE = 254 463 ALL = -1
An Enum for Bungie membership types.
182@attrs.define(auto_exc=True) 183class MembershipTypeError(BadRequest): 184 """A bad request error raised when passing wrong membership to the request. 185 186 Those fields are useful since it returns the correct membership and id which can be used 187 to make the request again with those fields. 188 189 Example 190 ------- 191 ```py 192 try: 193 profile = await client.fetch_profile( 194 member_id=1, 195 type=aiobungie.MembershipType.STADIA, 196 components=[] 197 ) 198 199 # Membership type is wrong! 200 except aiobungie.MembershipTypeError as err: 201 correct_membersip = err.into_membership() 202 profile_id = err.membership_id 203 204 # Recall the method. 205 profile = await client.fetch_profile( 206 member_id=profile_id, 207 type=correct_membership, 208 components=[] 209 ) 210 ``` 211 """ 212 213 membership_type: str 214 """The errored membership type passed to the request.""" 215 216 membership_id: int 217 """The errored user's membership id.""" 218 219 required_membership: str 220 """The required correct membership for errored user.""" 221 222 def into_membership( 223 self, value: typing.Optional[str] = None 224 ) -> enums.MembershipType: 225 """Turn the required membership from `str` into `aiobungie.Membership` type. 226 227 If value parameter is not provided it will fall back to the required membership. 228 """ 229 if value is None: 230 return _DETERMINE_MSHIP(self.required_membership) 231 return _DETERMINE_MSHIP(value) 232 233 def __str__(self) -> str: 234 return ( 235 f"Expected membership: {self.into_membership().name.replace('_', '').title()}, " 236 f"But got {self.into_membership(self.membership_type)} for id {self.membership_id}" 237 ) 238 239 def __int__(self) -> int: 240 return int(self.membership_id)
A bad request error raised when passing wrong membership to the request.
Those fields are useful since it returns the correct membership and id which can be used to make the request again with those fields.
Example
try:
profile = await client.fetch_profile(
member_id=1,
type=aiobungie.MembershipType.STADIA,
components=[]
)
# Membership type is wrong!
except aiobungie.MembershipTypeError as err:
correct_membersip = err.into_membership()
profile_id = err.membership_id
# Recall the method.
profile = await client.fetch_profile(
member_id=profile_id,
type=correct_membership,
components=[]
)
2def __init__(self, message, url, body, headers, membership_type, membership_id, required_membership): 3 self.message = message 4 self.url = url 5 self.body = body 6 self.headers = headers 7 self.http_status = attr_dict['http_status'].default 8 self.membership_type = membership_type 9 self.membership_id = membership_id 10 self.required_membership = required_membership 11 BaseException.__init__(self, self.message,self.url,self.body,self.headers,self.membership_type,self.membership_id,self.required_membership)
Method generated by attrs for class MembershipTypeError.
222 def into_membership( 223 self, value: typing.Optional[str] = None 224 ) -> enums.MembershipType: 225 """Turn the required membership from `str` into `aiobungie.Membership` type. 226 227 If value parameter is not provided it will fall back to the required membership. 228 """ 229 if value is None: 230 return _DETERMINE_MSHIP(self.required_membership) 231 return _DETERMINE_MSHIP(value)
Turn the required membership from str into aiobungie.Membership type.
If value parameter is not provided it will fall back to the required membership.
Inherited Members
- builtins.BaseException
- with_traceback
- args
495@typing.final 496class MilestoneType(int, Enum): 497 """An Enum for Destiny 2 milestone types.""" 498 499 UNKNOWN = 0 500 TUTORIAL = 1 501 ONETIME = 2 502 WEEKLY = 3 503 DAILY = 4 504 SPECIAL = 5
An Enum for Destiny 2 milestone types.
146@attrs.define(auto_exc=True) 147class NotFound(HTTPException): 148 """Raised when an unknown resource was not found.""" 149 150 http_status: http.HTTPStatus = attrs.field( 151 default=http.HTTPStatus.NOT_FOUND, init=False 152 )
Raised when an unknown resource was not found.
2def __init__(self, *, error_code, throttle_seconds, url, body, headers, message, error_status, message_data): 3 self.error_code = error_code 4 self.throttle_seconds = throttle_seconds 5 self.url = url 6 self.body = body 7 self.headers = headers 8 self.message = message 9 self.error_status = error_status 10 self.message_data = message_data 11 self.http_status = attr_dict['http_status'].default 12 BaseException.__init__(self, self.error_code,self.throttle_seconds,self.url,self.body,self.headers,self.message,self.error_status,self.message_data)
Method generated by attrs for class NotFound.
Inherited Members
- builtins.BaseException
- with_traceback
- args
94@typing.final 95class ObjectiveUIStyle(int, enums.Enum): 96 NONE = 0 97 HIGHLIGHTED = 1 98 CRAFTING_WEAPON_LEVEL = 2 99 CRAFTING_WEAPON_LEVEL_PROGRESS = 3 100 CRAFTING_WEAPON_TIMESTAMP = 4 101 CRAFTING_MEMENTOS = 5 102 CRAFTING_MEMENTO_TITLE = 6
An enumeration.
220@typing.final 221class Place(int, Enum): 222 """An Enum for Destiny 2 Places and NOT Planets""" 223 224 ORBIT = 2961497387 225 SOCIAL = 4151112093 226 LIGHT_HOUSE = 4276116472 227 EXPLORE = 3497767639
An Enum for Destiny 2 Places and NOT Planets
185@typing.final 186class Planet(int, Enum): 187 """An Enum for all available planets in Destiny 2.""" 188 189 UNKNOWN = 0 190 """Unknown space""" 191 192 EARTH = 3747705955 193 """Earth""" 194 195 DREAMING_CITY = 2877881518 196 """The Dreaming city.""" 197 198 NESSUS = 3526908984 199 """Nessus""" 200 201 MOON = 3325508439 202 """The Moon""" 203 204 COSMODROME = 3990611421 205 """The Cosmodrome""" 206 207 TANGLED_SHORE = 3821439926 208 """The Tangled Shore""" 209 210 VENUS = 3871070152 211 """Venus""" 212 213 EAZ = 541863059 # Exclusive event. 214 """European Aerial Zone""" 215 216 EUROPA = 1729879943 217 """Europa"""
An Enum for all available planets in Destiny 2.
672@typing.final 673class Presence(int, Enum): 674 """An enum for a bungie friend status.""" 675 676 OFFLINE_OR_UNKNOWN = 0 677 ONLINE = 1
An enum for a bungie friend status.
760@typing.final 761class PrivacySetting(int, Enum): 762 """An enum for players's privacy settings.""" 763 764 OPEN = 0 765 CLAN_AND_FRIENDS = 1 766 FRIENDS_ONLY = 2 767 INVITE_ONLY = 3 768 CLOSED = 4
An enum for players's privacy settings.
313class RESTClient(interfaces.RESTInterface): 314 """A RESTful client implementation for Bungie's API. 315 316 This client is designed to only make HTTP requests and return JSON objects 317 to provide RESTful functionality. 318 319 This client is also used within `aiobungie.Client` which deserialize those returned JSON objects 320 using the factory into Pythonic data classes objects which provide Python functionality. 321 322 Example 323 ------- 324 ```py 325 import aiobungie 326 327 async def main(): 328 async with aiobungie.RESTClient("TOKEN") as rest_client: 329 req = await rest_client.fetch_clan_members(4389205) 330 clan_members = req['results'] 331 for member in clan_members: 332 for k, v in member['destinyUserInfo'].items(): 333 print(k, v) 334 ``` 335 336 Parameters 337 ---------- 338 token : `str` 339 A valid application token from Bungie's developer portal. 340 341 Other Parameters 342 ---------------- 343 max_retries : `int` 344 The max retries number to retry if the request hit a `5xx` status code. 345 client_secret : `typing.Optional[str]` 346 An optional application client secret, 347 This is only needed if you're fetching OAuth2 tokens with this client. 348 client_id : `typing.Optional[int]` 349 An optional application client id, 350 This is only needed if you're fetching OAuth2 tokens with this client. 351 enable_debugging : `bool | str` 352 Whether to enable logging responses or not. 353 354 Logging Levels 355 -------------- 356 * `False`: This will disable logging. 357 * `True`: This will set the level to `DEBUG` and enable logging minimal information. 358 * `"TRACE" | aiobungie.TRACE`: This will log the response headers along with the minimal information. 359 """ 360 361 __slots__ = ( 362 "_token", 363 "_session", 364 "_lock", 365 "_max_retries", 366 "_client_secret", 367 "_client_id", 368 "_metadata", 369 ) 370 371 def __init__( 372 self, 373 token: str, 374 /, 375 *, 376 client_secret: typing.Optional[str] = None, 377 client_id: typing.Optional[int] = None, 378 client_session: typing.Optional[aiohttp.ClientSession] = None, 379 max_retries: int = 4, 380 enable_debugging: typing.Union[typing.Literal["TRACE"], bool, int] = False, 381 ) -> None: 382 self._session: typing.Optional[aiohttp.ClientSession] = client_session 383 self._lock: typing.Optional[asyncio.Lock] = None 384 self._client_secret = client_secret 385 self._client_id = client_id 386 self._token: str = token 387 self._max_retries = max_retries 388 self._metadata: collections.MutableMapping[typing.Any, typing.Any] = {} 389 390 self._set_debug_level(enable_debugging) 391 392 @property 393 def client_id(self) -> typing.Optional[int]: 394 return self._client_id 395 396 @property 397 def metadata(self) -> collections.MutableMapping[typing.Any, typing.Any]: 398 return self._metadata 399 400 @property 401 def is_alive(self) -> bool: 402 return self._session is not None 403 404 @typing.final 405 async def close(self) -> None: 406 if self._session is None: 407 raise RuntimeError("REST client is not running.") 408 409 await self._session.close() 410 self._session = None 411 412 @typing.final 413 def open(self) -> None: 414 """Open a new client session. This is called internally with contextmanager usage.""" 415 if self._session: 416 raise RuntimeError("Cannot open REST client when it's already open.") 417 418 self._session = aiohttp.ClientSession( 419 connector=aiohttp.TCPConnector(ssl=False), 420 raise_for_status=False, 421 timeout=aiohttp.ClientTimeout(total=30.0), 422 ) 423 424 @typing.final 425 def enable_debugging( 426 self, 427 level: typing.Union[typing.Literal["TRACE"], bool, int] = False, 428 file: typing.Optional[typing.Union[pathlib.Path, str]] = None, 429 /, 430 ) -> None: 431 self._set_debug_level(level, file) 432 433 @typing.final 434 async def static_request( 435 self, 436 method: typing.Union[RequestMethod, str], 437 path: str, 438 *, 439 auth: typing.Optional[str] = None, 440 json: typing.Optional[dict[str, typing.Any]] = None, 441 ) -> ResponseSig: 442 return await self._request(method, path, auth=auth, json=json) 443 444 @typing.final 445 def build_oauth2_url( 446 self, client_id: typing.Optional[int] = None 447 ) -> typing.Optional[builders.OAuthURL]: 448 client_id = client_id or self._client_id 449 if client_id is None: 450 return None 451 452 return builders.OAuthURL(client_id=client_id) 453 454 @staticmethod 455 def _set_debug_level( 456 level: typing.Union[typing.Literal["TRACE"], bool, int] = False, 457 file: typing.Optional[typing.Union[pathlib.Path, str]] = None, 458 ) -> None: 459 file_handler = logging.FileHandler(file, mode="w") if file else None 460 if level == "TRACE" or level == TRACE: 461 logging.basicConfig( 462 level=TRACE, handlers=[file_handler] if file_handler else None 463 ) 464 465 elif level: 466 logging.basicConfig( 467 level=logging.DEBUG, handlers=[file_handler] if file_handler else None 468 ) 469 470 async def _request( 471 self, 472 method: typing.Union[RequestMethod, str], 473 route: str, 474 *, 475 base: bool = False, 476 oauth2: bool = False, 477 auth: typing.Optional[str] = None, 478 unwrapping: typing.Literal["json", "read"] = "json", 479 json: typing.Optional[dict[str, typing.Any]] = None, 480 headers: typing.Optional[dict[str, typing.Any]] = None, 481 data: typing.Optional[typing.Union[str, dict[str, typing.Any]]] = None, 482 ) -> ResponseSig: 483 # This is not None when opening the client. 484 assert self._session is not None 485 486 retries: int = 0 487 headers = headers or {} 488 489 headers.setdefault(_USER_AGENT_HEADERS, _USER_AGENT) 490 headers["X-API-KEY"] = self._token 491 492 if auth is not None: 493 headers[_AUTH_HEADER] = f"Bearer {auth}" 494 495 # Handling endpoints 496 endpoint = url.BASE 497 498 if not base: 499 endpoint = endpoint + url.REST_EP 500 501 if oauth2: 502 headers["Content-Type"] = "application/x-www-form-urlencoded" 503 endpoint = endpoint + url.TOKEN_EP 504 505 if self._lock is None: 506 self._lock = asyncio.Lock() 507 508 while True: 509 async with (stack := contextlib.AsyncExitStack()): 510 await stack.enter_async_context(self._lock) 511 512 # We make the request here. 513 taken_time = time.monotonic() 514 response = await stack.enter_async_context( 515 self._session.request( 516 method=method, 517 url=f"{endpoint}/{route}", 518 json=json, 519 headers=headers, 520 data=data, 521 ) 522 ) 523 response_time = (time.monotonic() - taken_time) * 1_000 524 525 _LOG.debug( 526 "%s %s %s Time %.4fms", 527 method, 528 f"{endpoint}/{route}", 529 f"{response.status} {response.reason}", 530 response_time, 531 ) 532 533 await self._handle_ratelimit(response, method, route) 534 535 if response.status == http.HTTPStatus.NO_CONTENT: 536 return None 537 538 if 300 > response.status >= 200: 539 if unwrapping == "read": 540 # We need to read the bytes for the manifest response. 541 return await response.read() 542 543 if response.content_type == _APP_JSON: 544 json_data = await response.json() 545 546 _LOG.debug( 547 "%s %s %s Time %.4fms", 548 method, 549 f"{endpoint}/{route}", 550 f"{response.status} {response.reason}", 551 response_time, 552 ) 553 554 if _LOG.isEnabledFor(TRACE): 555 cloned = headers.copy() 556 cloned.update(response.headers) # type: ignore 557 558 _LOG.log( 559 TRACE, 560 "%s", 561 error.stringify_http_message(cloned), 562 ) 563 564 # Return the response. 565 # oauth2 responses are not packed inside a Response object. 566 if oauth2: 567 return json_data # type: ignore[no-any-return] 568 569 return json_data["Response"] # type: ignore[no-any-return] 570 571 if ( 572 response.status in _RETRY_5XX 573 and retries < self._max_retries # noqa: W503 574 ): 575 backoff_ = backoff.ExponentialBackOff(maximum=6) 576 sleep_time = next(backoff_) 577 _LOG.warning( 578 "Got %i - %s. Sleeping for %.2f seconds. Remaining retries: %i", 579 response.status, 580 response.reason, 581 sleep_time, 582 self._max_retries - retries, 583 ) 584 585 retries += 1 586 await asyncio.sleep(sleep_time) 587 continue 588 589 raise await error.raise_error(response) 590 591 if not typing.TYPE_CHECKING: 592 593 def __enter__(self) -> typing.NoReturn: 594 cls = type(self) 595 raise TypeError( 596 f"{cls.__qualname__} is async only, use 'async with' instead." 597 ) 598 599 def __exit__( 600 self, 601 exception_type: typing.Optional[type[BaseException]], 602 exception: typing.Optional[BaseException], 603 exception_traceback: typing.Optional[types.TracebackType], 604 ) -> None: 605 ... 606 607 async def __aenter__(self) -> RESTClient: 608 self.open() 609 return self 610 611 async def __aexit__( 612 self, 613 exception_type: typing.Optional[type[BaseException]], 614 exception: typing.Optional[BaseException], 615 exception_traceback: typing.Optional[types.TracebackType], 616 ) -> None: 617 await self.close() 618 619 # We don't want this to be super complicated. 620 @typing.final 621 async def _handle_ratelimit( 622 self, 623 response: aiohttp.ClientResponse, 624 method: str, 625 route: str, 626 ) -> None: 627 if response.status != http.HTTPStatus.TOO_MANY_REQUESTS: 628 return 629 630 if response.content_type != _APP_JSON: 631 raise error.HTTPError( 632 f"Being ratelimited on non JSON request, {response.content_type}.", 633 http.HTTPStatus.TOO_MANY_REQUESTS, 634 ) 635 636 json: typedefs.JSONObject = await response.json() 637 retry_after = float(json.get("ThrottleSeconds", 15.0)) + 0.1 638 max_calls: int = 0 639 640 while True: 641 if max_calls == 10: 642 # Max retries by default. We raise an error here. 643 raise error.RateLimitedError( 644 body=json, 645 url=str(response.real_url), 646 retry_after=retry_after, 647 ) 648 649 # We sleep for a little bit to avoid funky behavior. 650 _LOG.warning( 651 "We're being ratelimited, Method %s Route %s. Sleeping for %.2fs.", 652 method, 653 route, 654 retry_after, 655 ) 656 await asyncio.sleep(retry_after) 657 max_calls += 1 658 continue 659 660 async def fetch_oauth2_tokens(self, code: str, /) -> builders.OAuth2Response: 661 if not isinstance(self._client_secret, (str, int)): 662 raise TypeError( 663 "Expected (str, int) for client secret " 664 f"but got {type(self._client_secret).__name__}" # type: ignore 665 ) 666 667 headers = { 668 "client_secret": self._client_secret, 669 } 670 671 data = ( 672 f"grant_type=authorization_code&code={code}" 673 f"&client_id={self._client_id}&client_secret={self._client_secret}" 674 ) 675 676 response = await self._request( 677 RequestMethod.POST, "", headers=headers, data=data, oauth2=True 678 ) 679 assert isinstance(response, dict) 680 return builders.OAuth2Response.build_response(response) 681 682 async def refresh_access_token( 683 self, refresh_token: str, / 684 ) -> builders.OAuth2Response: 685 if not isinstance(self._client_secret, (int, str)): 686 raise TypeError( 687 f"Expected (str, int) for client secret but got {type(self._client_secret).__name__}" # type: ignore 688 ) 689 690 data = { 691 "grant_type": "refresh_token", 692 "refresh_token": refresh_token, 693 "client_id": self._client_id, 694 "client_secret": self._client_secret, 695 "Content-Type": "application/x-www-form-urlencoded", 696 } 697 698 response = await self._request(RequestMethod.POST, "", data=data, oauth2=True) 699 assert isinstance(response, dict) 700 return builders.OAuth2Response.build_response(response) 701 702 async def fetch_bungie_user(self, id: int) -> typedefs.JSONObject: 703 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 704 resp = await self._request( 705 RequestMethod.GET, f"User/GetBungieNetUserById/{id}/" 706 ) 707 assert isinstance(resp, dict) 708 return resp 709 710 async def fetch_user_themes(self) -> typedefs.JSONArray: 711 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 712 resp = await self._request(RequestMethod.GET, "User/GetAvailableThemes/") 713 assert isinstance(resp, list) 714 return resp 715 716 async def fetch_membership_from_id( 717 self, 718 id: int, 719 type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE, 720 /, 721 ) -> typedefs.JSONObject: 722 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 723 resp = await self._request( 724 RequestMethod.GET, f"User/GetMembershipsById/{id}/{int(type)}" 725 ) 726 assert isinstance(resp, dict) 727 return resp 728 729 async def fetch_player( 730 self, 731 name: str, 732 code: int, 733 type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.ALL, 734 /, 735 ) -> typedefs.JSONArray: 736 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 737 resp = await self._request( 738 RequestMethod.POST, 739 f"Destiny2/SearchDestinyPlayerByBungieName/{int(type)}", 740 json={"displayName": name, "displayNameCode": code}, 741 ) 742 assert isinstance(resp, list) 743 return resp 744 745 async def search_users(self, name: str, /) -> typedefs.JSONObject: 746 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 747 resp = await self._request( 748 RequestMethod.POST, 749 "User/Search/GlobalName/0", 750 json={"displayNamePrefix": name}, 751 ) 752 assert isinstance(resp, dict) 753 return resp 754 755 async def fetch_clan_from_id( 756 self, id: int, /, access_token: typing.Optional[str] = None 757 ) -> typedefs.JSONObject: 758 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 759 resp = await self._request( 760 RequestMethod.GET, f"GroupV2/{id}", auth=access_token 761 ) 762 assert isinstance(resp, dict) 763 return resp 764 765 async def fetch_clan( 766 self, 767 name: str, 768 /, 769 access_token: typing.Optional[str] = None, 770 *, 771 type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN, 772 ) -> typedefs.JSONObject: 773 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 774 resp = await self._request( 775 RequestMethod.GET, f"GroupV2/Name/{name}/{int(type)}", auth=access_token 776 ) 777 assert isinstance(resp, dict) 778 return resp 779 780 async def fetch_clan_admins(self, clan_id: int, /) -> typedefs.JSONObject: 781 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 782 resp = await self._request( 783 RequestMethod.GET, f"GroupV2/{clan_id}/AdminsAndFounder/" 784 ) 785 assert isinstance(resp, dict) 786 return resp 787 788 async def fetch_clan_conversations(self, clan_id: int, /) -> typedefs.JSONArray: 789 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 790 resp = await self._request( 791 RequestMethod.GET, f"GroupV2/{clan_id}/OptionalConversations/" 792 ) 793 assert isinstance(resp, list) 794 return resp 795 796 async def fetch_application(self, appid: int, /) -> typedefs.JSONObject: 797 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 798 resp = await self._request(RequestMethod.GET, f"App/Application/{appid}") 799 assert isinstance(resp, dict) 800 return resp 801 802 async def fetch_character( 803 self, 804 member_id: int, 805 membership_type: typedefs.IntAnd[enums.MembershipType], 806 character_id: int, 807 components: list[enums.ComponentType], 808 auth: typing.Optional[str] = None, 809 ) -> typedefs.JSONObject: 810 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 811 collector = _collect_components(components) 812 response = await self._request( 813 RequestMethod.GET, 814 f"Destiny2/{int(membership_type)}/Profile/{member_id}/" 815 f"Character/{character_id}/?components={collector}", 816 auth=auth, 817 ) 818 assert isinstance(response, dict) 819 return response 820 821 async def fetch_activities( 822 self, 823 member_id: int, 824 character_id: int, 825 mode: typedefs.IntAnd[enums.GameMode], 826 membership_type: typedefs.IntAnd[ 827 enums.MembershipType 828 ] = enums.MembershipType.ALL, 829 *, 830 page: int = 0, 831 limit: int = 1, 832 ) -> typedefs.JSONObject: 833 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 834 resp = await self._request( 835 RequestMethod.GET, 836 f"Destiny2/{int(membership_type)}/Account/" 837 f"{member_id}/Character/{character_id}/Stats/Activities" 838 f"/?mode={int(mode)}&count={limit}&page={page}", 839 ) 840 assert isinstance(resp, dict) 841 return resp 842 843 async def fetch_vendor_sales(self) -> typedefs.JSONObject: 844 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 845 resp = await self._request( 846 RequestMethod.GET, 847 f"Destiny2/Vendors/?components={int(enums.ComponentType.VENDOR_SALES)}", 848 ) 849 assert isinstance(resp, dict) 850 return resp 851 852 async def fetch_profile( 853 self, 854 membership_id: int, 855 type: typedefs.IntAnd[enums.MembershipType], 856 components: list[enums.ComponentType], 857 auth: typing.Optional[str] = None, 858 ) -> typedefs.JSONObject: 859 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 860 collector = _collect_components(components) 861 response = await self._request( 862 RequestMethod.GET, 863 f"Destiny2/{int(type)}/Profile/{membership_id}/?components={collector}", 864 auth=auth, 865 ) 866 assert isinstance(response, dict) 867 return response 868 869 async def fetch_entity(self, type: str, hash: int) -> typedefs.JSONObject: 870 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 871 response = await self._request( 872 RequestMethod.GET, route=f"Destiny2/Manifest/{type}/{hash}" 873 ) 874 assert isinstance(response, dict) 875 return response 876 877 async def fetch_inventory_item(self, hash: int, /) -> typedefs.JSONObject: 878 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 879 resp = await self.fetch_entity("DestinyInventoryItemDefinition", hash) 880 assert isinstance(resp, dict) 881 return resp 882 883 async def fetch_objective_entity(self, hash: int, /) -> typedefs.JSONObject: 884 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 885 resp = await self.fetch_entity("DestinyObjectiveDefinition", hash) 886 assert isinstance(resp, dict) 887 return resp 888 889 async def fetch_groups_for_member( 890 self, 891 member_id: int, 892 member_type: typedefs.IntAnd[enums.MembershipType], 893 /, 894 *, 895 filter: int = 0, 896 group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN, 897 ) -> typedefs.JSONObject: 898 resp = await self._request( 899 RequestMethod.GET, 900 f"GroupV2/User/{int(member_type)}/{member_id}/{filter}/{int(group_type)}/", 901 ) 902 assert isinstance(resp, dict) 903 return resp 904 905 async def fetch_potential_groups_for_member( 906 self, 907 member_id: int, 908 member_type: typedefs.IntAnd[enums.MembershipType], 909 /, 910 *, 911 filter: int = 0, 912 group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN, 913 ) -> typedefs.JSONObject: 914 resp = await self._request( 915 RequestMethod.GET, 916 f"GroupV2/User/Potential/{int(member_type)}/{member_id}/{filter}/{int(group_type)}/", 917 ) 918 assert isinstance(resp, dict) 919 return resp 920 921 async def fetch_clan_members( 922 self, 923 clan_id: int, 924 /, 925 *, 926 name: typing.Optional[str] = None, 927 type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE, 928 ) -> typedefs.JSONObject: 929 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 930 resp = await self._request( 931 RequestMethod.GET, 932 f"/GroupV2/{clan_id}/Members/?memberType={int(type)}&nameSearch={name if name else ''}¤tpage=1", 933 ) 934 assert isinstance(resp, dict) 935 return resp 936 937 async def fetch_hardlinked_credentials( 938 self, 939 credential: int, 940 type: typedefs.IntAnd[enums.CredentialType] = enums.CredentialType.STEAMID, 941 /, 942 ) -> typedefs.JSONObject: 943 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 944 resp = await self._request( 945 RequestMethod.GET, 946 f"User/GetMembershipFromHardLinkedCredential/{int(type)}/{credential}/", 947 ) 948 assert isinstance(resp, dict) 949 return resp 950 951 async def fetch_user_credentials( 952 self, access_token: str, membership_id: int, / 953 ) -> typedefs.JSONArray: 954 resp = await self._request( 955 RequestMethod.GET, 956 f"User/GetCredentialTypesForTargetAccount/{membership_id}", 957 auth=access_token, 958 ) 959 assert isinstance(resp, list) 960 return resp 961 962 async def insert_socket_plug( 963 self, 964 action_token: str, 965 /, 966 instance_id: int, 967 plug: typing.Union[builders.PlugSocketBuilder, dict[str, int]], 968 character_id: int, 969 membership_type: typedefs.IntAnd[enums.MembershipType], 970 ) -> typedefs.JSONObject: 971 if isinstance(plug, builders.PlugSocketBuilder): 972 plug = plug.collect() 973 974 body = { 975 "actionToken": action_token, 976 "itemInstanceId": instance_id, 977 "plug": plug, 978 "characterId": character_id, 979 "membershipType": int(membership_type), 980 } 981 resp = await self._request( 982 RequestMethod.POST, "Destiny2/Actions/Items/InsertSocketPlug", json=body 983 ) 984 assert isinstance(resp, dict) 985 return resp 986 987 async def insert_socket_plug_free( 988 self, 989 access_token: str, 990 /, 991 instance_id: int, 992 plug: typing.Union[builders.PlugSocketBuilder, dict[str, int]], 993 character_id: int, 994 membership_type: typedefs.IntAnd[enums.MembershipType], 995 ) -> typedefs.JSONObject: 996 if isinstance(plug, builders.PlugSocketBuilder): 997 plug = plug.collect() 998 999 body = { 1000 "itemInstanceId": instance_id, 1001 "plug": plug, 1002 "characterId": character_id, 1003 "membershipType": int(membership_type), 1004 } 1005 resp = await self._request( 1006 RequestMethod.POST, 1007 "Destiny2/Actions/Items/InsertSocketPlugFree", 1008 json=body, 1009 auth=access_token, 1010 ) 1011 assert isinstance(resp, dict) 1012 return resp 1013 1014 async def set_item_lock_state( 1015 self, 1016 access_token: str, 1017 state: bool, 1018 /, 1019 item_id: int, 1020 character_id: int, 1021 membership_type: typedefs.IntAnd[enums.MembershipType], 1022 ) -> int: 1023 body = { 1024 "state": state, 1025 "itemId": item_id, 1026 "characterId": character_id, 1027 "membershipType": int(membership_type), 1028 } 1029 response = await self._request( 1030 RequestMethod.POST, 1031 "Destiny2/Actions/Items/SetLockState", 1032 json=body, 1033 auth=access_token, 1034 ) 1035 assert isinstance(response, int) 1036 return response 1037 1038 async def set_quest_track_state( 1039 self, 1040 access_token: str, 1041 state: bool, 1042 /, 1043 item_id: int, 1044 character_id: int, 1045 membership_type: typedefs.IntAnd[enums.MembershipType], 1046 ) -> int: 1047 body = { 1048 "state": state, 1049 "itemId": item_id, 1050 "characterId": character_id, 1051 "membership_type": int(membership_type), 1052 } 1053 response = await self._request( 1054 RequestMethod.POST, 1055 "Destiny2/Actions/Items/SetTrackedState", 1056 json=body, 1057 auth=access_token, 1058 ) 1059 assert isinstance(response, int) 1060 return response 1061 1062 async def fetch_manifest_path(self) -> typedefs.JSONObject: 1063 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1064 path = await self._request(RequestMethod.GET, "Destiny2/Manifest") 1065 assert isinstance(path, dict) 1066 return path 1067 1068 async def read_manifest_bytes(self, language: str = "en", /) -> bytes: 1069 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1070 _ensure_manifest_language(language) 1071 1072 content = await self.fetch_manifest_path() 1073 resp = await self._request( 1074 RequestMethod.GET, 1075 content["mobileWorldContentPaths"][language], 1076 unwrapping="read", 1077 base=True, 1078 ) 1079 assert isinstance(resp, bytes) 1080 return resp 1081 1082 async def download_manifest( 1083 self, 1084 language: str = "en", 1085 name: str = "manifest", 1086 path: typing.Union[pathlib.Path, str] = ".", 1087 *, 1088 force: bool = False, 1089 ) -> None: 1090 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1091 complete_path = _get_path(name, path, sql=True) 1092 1093 if complete_path.exists() and force: 1094 if force: 1095 _LOG.info( 1096 f"Found manifest in {complete_path!s}. Forcing to Re-Download." 1097 ) 1098 complete_path.unlink(missing_ok=True) 1099 1100 return await self.download_manifest(language, name, path, force=force) 1101 1102 else: 1103 raise FileExistsError( 1104 "Manifest file already exists, " 1105 "To force download, set the `force` parameter to `True`." 1106 ) 1107 1108 _LOG.info(f"Downloading manifest. Location: {complete_path!s}") 1109 data_bytes = await self.read_manifest_bytes(language) 1110 await asyncio.get_running_loop().run_in_executor( 1111 None, _write_sqlite_bytes, data_bytes, path, name 1112 ) 1113 1114 async def download_json_manifest( 1115 self, 1116 file_name: str = "manifest", 1117 path: typing.Union[str, pathlib.Path] = ".", 1118 language: str = "en", 1119 ) -> None: 1120 _ensure_manifest_language(language) 1121 1122 _LOG.info(f"Downloading manifest JSON to {_get_path(file_name, path)!r}...") 1123 1124 content = await self.fetch_manifest_path() 1125 json_bytes = await self._request( 1126 RequestMethod.GET, 1127 content["jsonWorldContentPaths"][language], 1128 unwrapping="read", 1129 base=True, 1130 ) 1131 1132 await asyncio.get_running_loop().run_in_executor( 1133 None, _write_json_bytes, json_bytes, file_name, path 1134 ) 1135 _LOG.info("Finished downloading manifest JSON.") 1136 1137 async def fetch_manifest_version(self) -> str: 1138 return typing.cast(str, (await self.fetch_manifest_path())["version"]) 1139 1140 async def fetch_linked_profiles( 1141 self, 1142 member_id: int, 1143 member_type: typedefs.IntAnd[enums.MembershipType], 1144 /, 1145 *, 1146 all: bool = False, 1147 ) -> typedefs.JSONObject: 1148 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1149 resp = await self._request( 1150 RequestMethod.GET, 1151 f"Destiny2/{int(member_type)}/Profile/{member_id}/LinkedProfiles/?getAllMemberships={all}", 1152 ) 1153 assert isinstance(resp, dict) 1154 return resp 1155 1156 async def fetch_clan_banners(self) -> typedefs.JSONObject: 1157 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1158 resp = await self._request( 1159 RequestMethod.GET, "Destiny2/Clan/ClanBannerDictionary/" 1160 ) 1161 assert isinstance(resp, dict) 1162 return resp 1163 1164 async def fetch_public_milestones(self) -> typedefs.JSONObject: 1165 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1166 resp = await self._request(RequestMethod.GET, "Destiny2/Milestones/") 1167 assert isinstance(resp, dict) 1168 return resp 1169 1170 async def fetch_public_milestone_content( 1171 self, milestone_hash: int, / 1172 ) -> typedefs.JSONObject: 1173 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1174 resp = await self._request( 1175 RequestMethod.GET, f"Destiny2/Milestones/{milestone_hash}/Content/" 1176 ) 1177 assert isinstance(resp, dict) 1178 return resp 1179 1180 async def fetch_current_user_memberships( 1181 self, access_token: str, / 1182 ) -> typedefs.JSONObject: 1183 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1184 resp = await self._request( 1185 RequestMethod.GET, 1186 "User/GetMembershipsForCurrentUser/", 1187 auth=access_token, 1188 ) 1189 assert isinstance(resp, dict) 1190 return resp 1191 1192 async def equip_item( 1193 self, 1194 access_token: str, 1195 /, 1196 item_id: int, 1197 character_id: int, 1198 membership_type: typedefs.IntAnd[enums.MembershipType], 1199 ) -> None: 1200 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1201 payload = { 1202 "itemId": item_id, 1203 "characterId": character_id, 1204 "membershipType": int(membership_type), 1205 } 1206 1207 await self._request( 1208 RequestMethod.POST, 1209 "Destiny2/Actions/Items/EquipItem/", 1210 json=payload, 1211 auth=access_token, 1212 ) 1213 1214 async def equip_items( 1215 self, 1216 access_token: str, 1217 /, 1218 item_ids: list[int], 1219 character_id: int, 1220 membership_type: typedefs.IntAnd[enums.MembershipType], 1221 ) -> None: 1222 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1223 payload = { 1224 "itemIds": item_ids, 1225 "characterId": character_id, 1226 "membershipType": int(membership_type), 1227 } 1228 await self._request( 1229 RequestMethod.POST, 1230 "Destiny2/Actions/Items/EquipItems/", 1231 json=payload, 1232 auth=access_token, 1233 ) 1234 1235 async def ban_clan_member( 1236 self, 1237 access_token: str, 1238 /, 1239 group_id: int, 1240 membership_id: int, 1241 membership_type: typedefs.IntAnd[enums.MembershipType], 1242 *, 1243 length: int = 0, 1244 comment: undefined.UndefinedOr[str] = undefined.UNDEFINED, 1245 ) -> None: 1246 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1247 payload = {"comment": str(comment), "length": length} 1248 await self._request( 1249 RequestMethod.POST, 1250 f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Ban/", 1251 json=payload, 1252 auth=access_token, 1253 ) 1254 1255 async def unban_clan_member( 1256 self, 1257 access_token: str, 1258 /, 1259 group_id: int, 1260 membership_id: int, 1261 membership_type: typedefs.IntAnd[enums.MembershipType], 1262 ) -> None: 1263 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1264 await self._request( 1265 RequestMethod.POST, 1266 f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Unban/", 1267 auth=access_token, 1268 ) 1269 1270 async def kick_clan_member( 1271 self, 1272 access_token: str, 1273 /, 1274 group_id: int, 1275 membership_id: int, 1276 membership_type: typedefs.IntAnd[enums.MembershipType], 1277 ) -> typedefs.JSONObject: 1278 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1279 resp = await self._request( 1280 RequestMethod.POST, 1281 f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Kick/", 1282 auth=access_token, 1283 ) 1284 assert isinstance(resp, dict) 1285 return resp 1286 1287 async def edit_clan( 1288 self, 1289 access_token: str, 1290 /, 1291 group_id: int, 1292 *, 1293 name: typedefs.NoneOr[str] = None, 1294 about: typedefs.NoneOr[str] = None, 1295 motto: typedefs.NoneOr[str] = None, 1296 theme: typedefs.NoneOr[str] = None, 1297 tags: typedefs.NoneOr[collections.Sequence[str]] = None, 1298 is_public: typedefs.NoneOr[bool] = None, 1299 locale: typedefs.NoneOr[str] = None, 1300 avatar_image_index: typedefs.NoneOr[int] = None, 1301 membership_option: typedefs.NoneOr[ 1302 typedefs.IntAnd[enums.MembershipOption] 1303 ] = None, 1304 allow_chat: typedefs.NoneOr[bool] = None, 1305 chat_security: typedefs.NoneOr[typing.Literal[0, 1]] = None, 1306 call_sign: typedefs.NoneOr[str] = None, 1307 homepage: typedefs.NoneOr[typing.Literal[0, 1, 2]] = None, 1308 enable_invite_messaging_for_admins: typedefs.NoneOr[bool] = None, 1309 default_publicity: typedefs.NoneOr[typing.Literal[0, 1, 2]] = None, 1310 is_public_topic_admin: typedefs.NoneOr[bool] = None, 1311 ) -> None: 1312 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1313 payload = { 1314 "name": name, 1315 "about": about, 1316 "motto": motto, 1317 "theme": theme, 1318 "tags": tags, 1319 "isPublic": is_public, 1320 "avatarImageIndex": avatar_image_index, 1321 "isPublicTopicAdminOnly": is_public_topic_admin, 1322 "allowChat": allow_chat, 1323 "chatSecurity": chat_security, 1324 "callsign": call_sign, 1325 "homepage": homepage, 1326 "enableInvitationMessagingForAdmins": enable_invite_messaging_for_admins, 1327 "defaultPublicity": default_publicity, 1328 "locale": locale, 1329 } 1330 if membership_option is not None: 1331 payload["membershipOption"] = int(membership_option) 1332 1333 await self._request( 1334 RequestMethod.POST, 1335 f"GroupV2/{group_id}/Edit", 1336 json=payload, 1337 auth=access_token, 1338 ) 1339 1340 async def edit_clan_options( 1341 self, 1342 access_token: str, 1343 /, 1344 group_id: int, 1345 *, 1346 invite_permissions_override: typedefs.NoneOr[bool] = None, 1347 update_culture_permissionOverride: typedefs.NoneOr[bool] = None, 1348 host_guided_game_permission_override: typedefs.NoneOr[ 1349 typing.Literal[0, 1, 2] 1350 ] = None, 1351 update_banner_permission_override: typedefs.NoneOr[bool] = None, 1352 join_level: typedefs.NoneOr[typedefs.IntAnd[enums.ClanMemberType]] = None, 1353 ) -> None: 1354 payload = { 1355 "InvitePermissionOverride": invite_permissions_override, 1356 "UpdateCulturePermissionOverride": update_culture_permissionOverride, 1357 "HostGuidedGamePermissionOverride": host_guided_game_permission_override, 1358 "UpdateBannerPermissionOverride": update_banner_permission_override, 1359 "JoinLevel": int(join_level) if join_level else None, 1360 } 1361 1362 await self._request( 1363 RequestMethod.POST, 1364 f"GroupV2/{group_id}/EditFounderOptions", 1365 json=payload, 1366 auth=access_token, 1367 ) 1368 1369 async def fetch_friends(self, access_token: str, /) -> typedefs.JSONObject: 1370 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1371 resp = await self._request( 1372 RequestMethod.GET, 1373 "Social/Friends/", 1374 auth=access_token, 1375 ) 1376 assert isinstance(resp, dict) 1377 return resp 1378 1379 async def fetch_friend_requests(self, access_token: str, /) -> typedefs.JSONObject: 1380 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1381 resp = await self._request( 1382 RequestMethod.GET, 1383 "Social/Friends/Requests", 1384 auth=access_token, 1385 ) 1386 assert isinstance(resp, dict) 1387 return resp 1388 1389 async def accept_friend_request(self, access_token: str, /, member_id: int) -> None: 1390 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1391 await self._request( 1392 RequestMethod.POST, 1393 f"Social/Friends/Requests/Accept/{member_id}", 1394 auth=access_token, 1395 ) 1396 1397 async def send_friend_request(self, access_token: str, /, member_id: int) -> None: 1398 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1399 await self._request( 1400 RequestMethod.POST, 1401 f"Social/Friends/Add/{member_id}", 1402 auth=access_token, 1403 ) 1404 1405 async def decline_friend_request( 1406 self, access_token: str, /, member_id: int 1407 ) -> None: 1408 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1409 await self._request( 1410 RequestMethod.POST, 1411 f"Social/Friends/Requests/Decline/{member_id}", 1412 auth=access_token, 1413 ) 1414 1415 async def remove_friend(self, access_token: str, /, member_id: int) -> None: 1416 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1417 await self._request( 1418 RequestMethod.POST, 1419 f"Social/Friends/Remove/{member_id}", 1420 auth=access_token, 1421 ) 1422 1423 async def remove_friend_request(self, access_token: str, /, member_id: int) -> None: 1424 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> 1425 await self._request( 1426 RequestMethod.POST, 1427 f"Social/Friends/Requests/Remove/{member_id}", 1428 auth=access_token, 1429 ) 1430 1431 async def approve_all_pending_group_users( 1432 self, 1433 access_token: str, 1434 /, 1435 group_id: int, 1436 message: undefined.UndefinedOr[str] = undefined.UNDEFINED, 1437 ) -> None: 1438 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> 1439 await self._request( 1440 RequestMethod.POST, 1441 f"GroupV2/{group_id}/Members/ApproveAll", 1442 auth=access_token, 1443 json={"message": str(message)}, 1444 ) 1445 1446 async def deny_all_pending_group_users( 1447 self, 1448 access_token: str, 1449 /, 1450 group_id: int, 1451 *, 1452 message: undefined.UndefinedOr[str] = undefined.UNDEFINED, 1453 ) -> None: 1454 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> 1455 await self._request( 1456 RequestMethod.POST, 1457 f"GroupV2/{group_id}/Members/DenyAll", 1458 auth=access_token, 1459 json={"message": str(message)}, 1460 ) 1461 1462 async def add_optional_conversation( 1463 self, 1464 access_token: str, 1465 /, 1466 group_id: int, 1467 *, 1468 name: undefined.UndefinedOr[str] = undefined.UNDEFINED, 1469 security: typing.Literal[0, 1] = 0, 1470 ) -> None: 1471 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> 1472 payload = {"chatName": str(name), "chatSecurity": security} 1473 await self._request( 1474 RequestMethod.POST, 1475 f"GroupV2/{group_id}/OptionalConversations/Add", 1476 json=payload, 1477 auth=access_token, 1478 ) 1479 1480 async def edit_optional_conversation( 1481 self, 1482 access_token: str, 1483 /, 1484 group_id: int, 1485 conversation_id: int, 1486 *, 1487 name: undefined.UndefinedOr[str] = undefined.UNDEFINED, 1488 security: typing.Literal[0, 1] = 0, 1489 enable_chat: bool = False, 1490 ) -> None: 1491 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> 1492 payload = { 1493 "chatEnabled": enable_chat, 1494 "chatName": str(name), 1495 "chatSecurity": security, 1496 } 1497 await self._request( 1498 RequestMethod.POST, 1499 f"GroupV2/{group_id}/OptionalConversations/Edit/{conversation_id}", 1500 json=payload, 1501 auth=access_token, 1502 ) 1503 1504 async def transfer_item( 1505 self, 1506 access_token: str, 1507 /, 1508 item_id: int, 1509 item_hash: int, 1510 character_id: int, 1511 member_type: typedefs.IntAnd[enums.MembershipType], 1512 *, 1513 stack_size: int = 1, 1514 vault: bool = False, 1515 ) -> None: 1516 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> 1517 payload = { 1518 "characterId": character_id, 1519 "membershipType": int(member_type), 1520 "itemId": item_id, 1521 "itemReferenceHash": item_hash, 1522 "stackSize": stack_size, 1523 "transferToVault": vault, 1524 } 1525 await self._request( 1526 RequestMethod.POST, 1527 "Destiny2/Actions/Items/TransferItem", 1528 json=payload, 1529 auth=access_token, 1530 ) 1531 1532 async def pull_item( 1533 self, 1534 access_token: str, 1535 /, 1536 item_id: int, 1537 item_hash: int, 1538 character_id: int, 1539 member_type: typedefs.IntAnd[enums.MembershipType], 1540 *, 1541 stack_size: int = 1, 1542 vault: bool = False, 1543 ) -> None: 1544 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> 1545 payload = { 1546 "characterId": character_id, 1547 "membershipType": int(member_type), 1548 "itemId": item_id, 1549 "itemReferenceHash": item_hash, 1550 "stackSize": stack_size, 1551 "transferToVault": vault, 1552 } 1553 await self._request( 1554 RequestMethod.POST, 1555 "Destiny2/Actions/Items/PullFromPostmaster", 1556 json=payload, 1557 auth=access_token, 1558 ) 1559 1560 async def fetch_fireteams( 1561 self, 1562 activity_type: typedefs.IntAnd[fireteams.FireteamActivity], 1563 *, 1564 platform: typedefs.IntAnd[ 1565 fireteams.FireteamPlatform 1566 ] = fireteams.FireteamPlatform.ANY, 1567 language: typing.Union[ 1568 fireteams.FireteamLanguage, str 1569 ] = fireteams.FireteamLanguage.ALL, 1570 date_range: typedefs.IntAnd[ 1571 fireteams.FireteamDate 1572 ] = fireteams.FireteamDate.ALL, 1573 page: int = 0, 1574 slots_filter: int = 0, 1575 ) -> typedefs.JSONObject: 1576 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1577 resp = await self._request( 1578 RequestMethod.GET, 1579 f"Fireteam/Search/Available/{int(platform)}/{int(activity_type)}/{int(date_range)}/{slots_filter}/{page}/?langFilter={str(language)}", # noqa: E501 Line too long 1580 ) 1581 assert isinstance(resp, dict) 1582 return resp 1583 1584 async def fetch_avaliable_clan_fireteams( 1585 self, 1586 access_token: str, 1587 group_id: int, 1588 activity_type: typedefs.IntAnd[fireteams.FireteamActivity], 1589 *, 1590 platform: typedefs.IntAnd[fireteams.FireteamPlatform], 1591 language: typing.Union[fireteams.FireteamLanguage, str], 1592 date_range: typedefs.IntAnd[ 1593 fireteams.FireteamDate 1594 ] = fireteams.FireteamDate.ALL, 1595 page: int = 0, 1596 public_only: bool = False, 1597 slots_filter: int = 0, 1598 ) -> typedefs.JSONObject: 1599 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1600 resp = await self._request( 1601 RequestMethod.GET, 1602 f"Fireteam/Clan/{group_id}/Available/{int(platform)}/{int(activity_type)}/{int(date_range)}/{slots_filter}/{public_only}/{page}", # noqa: E501 1603 json={"langFilter": str(language)}, 1604 auth=access_token, 1605 ) 1606 assert isinstance(resp, dict) 1607 return resp 1608 1609 async def fetch_clan_fireteam( 1610 self, access_token: str, fireteam_id: int, group_id: int 1611 ) -> typedefs.JSONObject: 1612 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1613 resp = await self._request( 1614 RequestMethod.GET, 1615 f"Fireteam/Clan/{group_id}/Summary/{fireteam_id}", 1616 auth=access_token, 1617 ) 1618 assert isinstance(resp, dict) 1619 return resp 1620 1621 async def fetch_my_clan_fireteams( 1622 self, 1623 access_token: str, 1624 group_id: int, 1625 *, 1626 include_closed: bool = True, 1627 platform: typedefs.IntAnd[fireteams.FireteamPlatform], 1628 language: typing.Union[fireteams.FireteamLanguage, str], 1629 filtered: bool = True, 1630 page: int = 0, 1631 ) -> typedefs.JSONObject: 1632 payload = {"groupFilter": filtered, "langFilter": str(language)} 1633 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1634 resp = await self._request( 1635 RequestMethod.GET, 1636 f"Fireteam/Clan/{group_id}/My/{int(platform)}/{include_closed}/{page}", 1637 json=payload, 1638 auth=access_token, 1639 ) 1640 assert isinstance(resp, dict) 1641 return resp 1642 1643 async def fetch_private_clan_fireteams( 1644 self, access_token: str, group_id: int, / 1645 ) -> int: 1646 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1647 resp = await self._request( 1648 RequestMethod.GET, 1649 f"Fireteam/Clan/{group_id}/ActiveCount", 1650 auth=access_token, 1651 ) 1652 assert isinstance(resp, int) 1653 return resp 1654 1655 async def fetch_post_activity(self, instance_id: int, /) -> typedefs.JSONObject: 1656 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1657 resp = await self._request( 1658 RequestMethod.GET, f"Destiny2/Stats/PostGameCarnageReport/{instance_id}" 1659 ) 1660 assert isinstance(resp, dict) 1661 return resp 1662 1663 async def search_entities( 1664 self, name: str, entity_type: str, *, page: int = 0 1665 ) -> typedefs.JSONObject: 1666 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1667 resp = await self._request( 1668 RequestMethod.GET, 1669 f"Destiny2/Armory/Search/{entity_type}/{name}/", 1670 json={"page": page}, 1671 ) 1672 assert isinstance(resp, dict) 1673 return resp 1674 1675 async def fetch_unique_weapon_history( 1676 self, 1677 membership_id: int, 1678 character_id: int, 1679 membership_type: typedefs.IntAnd[enums.MembershipType], 1680 ) -> typedefs.JSONObject: 1681 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1682 resp = await self._request( 1683 RequestMethod.GET, 1684 f"Destiny2/{int(membership_type)}/Account/{membership_id}/Character/{character_id}/Stats/UniqueWeapons/", 1685 ) 1686 assert isinstance(resp, dict) 1687 return resp 1688 1689 async def fetch_item( 1690 self, 1691 member_id: int, 1692 item_id: int, 1693 membership_type: typedefs.IntAnd[enums.MembershipType], 1694 components: list[enums.ComponentType], 1695 ) -> typedefs.JSONObject: 1696 collector = _collect_components(components) 1697 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1698 resp = await self._request( 1699 RequestMethod.GET, 1700 f"Destiny2/{int(membership_type)}/Profile/{member_id}/Item/{item_id}/?components={collector}", 1701 ) 1702 assert isinstance(resp, dict) 1703 return resp 1704 1705 async def fetch_clan_weekly_rewards(self, clan_id: int, /) -> typedefs.JSONObject: 1706 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1707 resp = await self._request( 1708 RequestMethod.GET, f"Destiny2/Clan/{clan_id}/WeeklyRewardState/" 1709 ) 1710 assert isinstance(resp, dict) 1711 return resp 1712 1713 async def fetch_available_locales(self) -> typedefs.JSONObject: 1714 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1715 resp = await self._request( 1716 RequestMethod.GET, "Destiny2/Manifest/DestinyLocaleDefinition/" 1717 ) 1718 assert isinstance(resp, dict) 1719 return resp 1720 1721 async def fetch_common_settings(self) -> typedefs.JSONObject: 1722 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1723 resp = await self._request(RequestMethod.GET, "Settings") 1724 assert isinstance(resp, dict) 1725 return resp 1726 1727 async def fetch_user_systems_overrides(self) -> typedefs.JSONObject: 1728 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1729 resp = await self._request(RequestMethod.GET, "UserSystemOverrides") 1730 assert isinstance(resp, dict) 1731 return resp 1732 1733 async def fetch_global_alerts( 1734 self, *, include_streaming: bool = False 1735 ) -> typedefs.JSONArray: 1736 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1737 resp = await self._request( 1738 RequestMethod.GET, f"GlobalAlerts/?includestreaming={include_streaming}" 1739 ) 1740 assert isinstance(resp, list) 1741 return resp 1742 1743 async def awainitialize_request( 1744 self, 1745 access_token: str, 1746 type: typing.Literal[0, 1], 1747 membership_type: typedefs.IntAnd[enums.MembershipType], 1748 /, 1749 *, 1750 affected_item_id: typing.Optional[int] = None, 1751 character_id: typing.Optional[int] = None, 1752 ) -> typedefs.JSONObject: 1753 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1754 1755 body = {"type": type, "membershipType": int(membership_type)} 1756 1757 if affected_item_id is not None: 1758 body["affectedItemId"] = affected_item_id 1759 1760 if character_id is not None: 1761 body["characterId"] = character_id 1762 1763 resp = await self._request( 1764 RequestMethod.POST, "Destiny2/Awa/Initialize", json=body, auth=access_token 1765 ) 1766 assert isinstance(resp, dict) 1767 return resp 1768 1769 async def awaget_action_token( 1770 self, access_token: str, correlation_id: str, / 1771 ) -> typedefs.JSONObject: 1772 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1773 resp = await self._request( 1774 RequestMethod.POST, 1775 f"Destiny2/Awa/GetActionToken/{correlation_id}", 1776 auth=access_token, 1777 ) 1778 assert isinstance(resp, dict) 1779 return resp 1780 1781 async def awa_provide_authorization_result( 1782 self, 1783 access_token: str, 1784 selection: int, 1785 correlation_id: str, 1786 nonce: collections.MutableSequence[typing.Union[str, bytes]], 1787 ) -> int: 1788 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1789 1790 body = {"selection": selection, "correlationId": correlation_id, "nonce": nonce} 1791 1792 resp = await self._request( 1793 RequestMethod.POST, 1794 "Destiny2/Awa/AwaProvideAuthorizationResult", 1795 json=body, 1796 auth=access_token, 1797 ) 1798 assert isinstance(resp, int) 1799 return resp 1800 1801 async def fetch_vendors( 1802 self, 1803 access_token: str, 1804 character_id: int, 1805 membership_id: int, 1806 membership_type: typedefs.IntAnd[enums.MembershipType], 1807 /, 1808 components: list[enums.ComponentType], 1809 filter: typing.Optional[int] = None, 1810 ) -> typedefs.JSONObject: 1811 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1812 components_ = _collect_components(components) 1813 route = ( 1814 f"Destiny2/{int(membership_type)}/Profile/{membership_id}" 1815 f"/Character/{character_id}/Vendors/?components={components_}" 1816 ) 1817 1818 if filter is not None: 1819 route = route + f"&filter={filter}" 1820 1821 resp = await self._request( 1822 RequestMethod.GET, 1823 route, 1824 auth=access_token, 1825 ) 1826 assert isinstance(resp, dict) 1827 return resp 1828 1829 async def fetch_vendor( 1830 self, 1831 access_token: str, 1832 character_id: int, 1833 membership_id: int, 1834 membership_type: typedefs.IntAnd[enums.MembershipType], 1835 vendor_hash: int, 1836 /, 1837 components: list[enums.ComponentType], 1838 ) -> typedefs.JSONObject: 1839 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1840 components_ = _collect_components(components) 1841 resp = await self._request( 1842 RequestMethod.GET, 1843 ( 1844 f"Destiny2/{int(membership_type)}/Profile/{membership_id}" 1845 f"/Character/{character_id}/Vendors/{vendor_hash}/?components={components_}" 1846 ), 1847 auth=access_token, 1848 ) 1849 assert isinstance(resp, dict) 1850 return resp 1851 1852 async def fetch_application_api_usage( 1853 self, 1854 access_token: str, 1855 application_id: int, 1856 /, 1857 *, 1858 start: typing.Optional[datetime.datetime] = None, 1859 end: typing.Optional[datetime.datetime] = None, 1860 ) -> typedefs.JSONObject: 1861 end_date, start_date = time.parse_date_range(end, start) 1862 resp = await self._request( 1863 RequestMethod.GET, 1864 f"App/ApiUsage/{application_id}/?end={end_date}&start={start_date}", 1865 auth=access_token, 1866 ) 1867 assert isinstance(resp, dict) 1868 return resp 1869 1870 async def fetch_bungie_applications(self) -> typedefs.JSONArray: 1871 resp = await self._request(RequestMethod.GET, "App/FirstParty") 1872 assert isinstance(resp, list) 1873 return resp 1874 1875 async def fetch_content_type(self, type: str, /) -> typedefs.JSONObject: 1876 resp = await self._request(RequestMethod.GET, f"Content/GetContentType/{type}/") 1877 assert isinstance(resp, dict) 1878 return resp 1879 1880 async def fetch_content_by_id( 1881 self, id: int, locale: str, /, *, head: bool = False 1882 ) -> typedefs.JSONObject: 1883 resp = await self._request( 1884 RequestMethod.GET, 1885 f"Content/GetContentById/{id}/{locale}/", 1886 json={"head": head}, 1887 ) 1888 assert isinstance(resp, dict) 1889 return resp 1890 1891 async def fetch_content_by_tag_and_type( 1892 self, locale: str, tag: str, type: str, *, head: bool = False 1893 ) -> typedefs.JSONObject: 1894 resp = await self._request( 1895 RequestMethod.GET, 1896 f"Content/GetContentByTagAndType/{tag}/{type}/{locale}/", 1897 json={"head": head}, 1898 ) 1899 assert isinstance(resp, dict) 1900 return resp 1901 1902 async def search_content_with_text( 1903 self, 1904 locale: str, 1905 /, 1906 content_type: str, 1907 search_text: str, 1908 tag: str, 1909 *, 1910 page: undefined.UndefinedOr[int] = undefined.UNDEFINED, 1911 source: undefined.UndefinedOr[str] = undefined.UNDEFINED, 1912 ) -> typedefs.JSONObject: 1913 body: typedefs.JSONObject = {} 1914 1915 body["ctype"] = content_type 1916 body["searchtext"] = search_text 1917 body["tag"] = tag 1918 1919 if page is not undefined.UNDEFINED: 1920 body["currentpage"] = page 1921 else: 1922 body["currentpage"] = 1 1923 1924 if source is not undefined.UNDEFINED: 1925 body["source"] = source 1926 else: 1927 source = "" 1928 resp = await self._request( 1929 RequestMethod.GET, f"Content/Search/{locale}/", json=body 1930 ) 1931 assert isinstance(resp, dict) 1932 return resp 1933 1934 async def search_content_by_tag_and_type( 1935 self, 1936 locale: str, 1937 tag: str, 1938 type: str, 1939 *, 1940 page: undefined.UndefinedOr[int] = undefined.UNDEFINED, 1941 ) -> typedefs.JSONObject: 1942 body: typedefs.JSONObject = {} 1943 body["currentpage"] = 1 if page is undefined.UNDEFINED else page 1944 resp = await self._request( 1945 RequestMethod.GET, 1946 f"Content/SearchContentByTagAndType/{tag}/{type}/{locale}/", 1947 json=body, 1948 ) 1949 assert isinstance(resp, dict) 1950 return resp 1951 1952 async def search_help_articles( 1953 self, text: str, size: str, / 1954 ) -> typedefs.JSONObject: 1955 resp = await self._request( 1956 RequestMethod.GET, f"Content/SearchHelpArticles/{text}/{size}/" 1957 ) 1958 assert isinstance(resp, dict) 1959 return resp 1960 1961 async def fetch_topics_page( 1962 self, 1963 category_filter: int, 1964 group: int, 1965 date_filter: int, 1966 sort: typing.Union[str, bytes], 1967 *, 1968 page: undefined.UndefinedOr[int] = undefined.UNDEFINED, 1969 locales: undefined.UndefinedOr[collections.Iterable[str]] = undefined.UNDEFINED, 1970 tag_filter: undefined.UndefinedOr[str] = undefined.UNDEFINED, 1971 ) -> typedefs.JSONObject: 1972 body: typedefs.JSONObject = {} 1973 if locales is not undefined.UNDEFINED: 1974 body["locales"] = ",".join(str(locales)) 1975 else: 1976 body["locales"] = ",".join([]) 1977 1978 if tag_filter is not undefined.UNDEFINED: 1979 body["tagstring"] = tag_filter 1980 else: 1981 body["tagstring"] = "" 1982 1983 page = 0 if page is not undefined.UNDEFINED else page 1984 1985 resp = await self._request( 1986 RequestMethod.GET, 1987 f"Forum/GetTopicsPaged/{page}/{0}/{group}/{sort!s}/{date_filter}/{category_filter}/", 1988 json=body, 1989 ) 1990 assert isinstance(resp, dict) 1991 return resp 1992 1993 async def fetch_core_topics_page( 1994 self, 1995 category_filter: int, 1996 date_filter: int, 1997 sort: typing.Union[str, bytes], 1998 *, 1999 page: undefined.UndefinedOr[int] = undefined.UNDEFINED, 2000 locales: undefined.UndefinedOr[collections.Iterable[str]] = undefined.UNDEFINED, 2001 ) -> typedefs.JSONObject: 2002 body: typedefs.JSONObject = {} 2003 2004 if locales is not undefined.UNDEFINED: 2005 body["locales"] = ",".join(str(locales)) 2006 else: 2007 body["locales"] = ",".join([]) 2008 2009 resp = await self._request( 2010 RequestMethod.GET, 2011 f"Forum/GetCoreTopicsPaged/{0 if page is undefined.UNDEFINED else page}" 2012 f"/{sort!s}/{date_filter}/{category_filter}/", 2013 json=body, 2014 ) 2015 assert isinstance(resp, dict) 2016 return resp 2017 2018 async def fetch_posts_threaded_page( 2019 self, 2020 parent_post: bool, 2021 page: int, 2022 page_size: int, 2023 parent_post_id: int, 2024 reply_size: int, 2025 root_thread_mode: bool, 2026 sort_mode: int, 2027 show_banned: typing.Optional[str] = None, 2028 ) -> typedefs.JSONObject: 2029 resp = await self._request( 2030 RequestMethod.GET, 2031 f"Forum/GetPostsThreadedPaged/{parent_post}/{page}/" 2032 f"{page_size}/{reply_size}/{parent_post_id}/{root_thread_mode}/{sort_mode}/", 2033 json={"showbanned": show_banned}, 2034 ) 2035 assert isinstance(resp, dict) 2036 return resp 2037 2038 async def fetch_posts_threaded_page_from_child( 2039 self, 2040 child_id: bool, 2041 page: int, 2042 page_size: int, 2043 reply_size: int, 2044 root_thread_mode: bool, 2045 sort_mode: int, 2046 show_banned: typing.Optional[str] = None, 2047 ) -> typedefs.JSONObject: 2048 resp = await self._request( 2049 RequestMethod.GET, 2050 f"Forum/GetPostsThreadedPagedFromChild/{child_id}/" 2051 f"{page}/{page_size}/{reply_size}/{root_thread_mode}/{sort_mode}/", 2052 json={"showbanned": show_banned}, 2053 ) 2054 assert isinstance(resp, dict) 2055 return resp 2056 2057 async def fetch_post_and_parent( 2058 self, child_id: int, /, *, show_banned: typing.Optional[str] = None 2059 ) -> typedefs.JSONObject: 2060 resp = await self._request( 2061 RequestMethod.GET, 2062 f"Forum/GetPostAndParent/{child_id}/", 2063 json={"showbanned": show_banned}, 2064 ) 2065 assert isinstance(resp, dict) 2066 return resp 2067 2068 async def fetch_posts_and_parent_awaiting( 2069 self, child_id: int, /, *, show_banned: typing.Optional[str] = None 2070 ) -> typedefs.JSONObject: 2071 resp = await self._request( 2072 RequestMethod.GET, 2073 f"Forum/GetPostAndParentAwaitingApproval/{child_id}/", 2074 json={"showbanned": show_banned}, 2075 ) 2076 assert isinstance(resp, dict) 2077 return resp 2078 2079 async def fetch_topic_for_content(self, content_id: int, /) -> int: 2080 resp = await self._request( 2081 RequestMethod.GET, f"Forum/GetTopicForContent/{content_id}/" 2082 ) 2083 assert isinstance(resp, int) 2084 return resp 2085 2086 async def fetch_forum_tag_suggestions( 2087 self, partial_tag: str, / 2088 ) -> typedefs.JSONObject: 2089 resp = await self._request( 2090 RequestMethod.GET, 2091 "Forum/GetForumTagSuggestions/", 2092 json={"partialtag": partial_tag}, 2093 ) 2094 assert isinstance(resp, dict) 2095 return resp 2096 2097 async def fetch_poll(self, topic_id: int, /) -> typedefs.JSONObject: 2098 resp = await self._request(RequestMethod.GET, f"Forum/Poll/{topic_id}/") 2099 assert isinstance(resp, dict) 2100 return resp 2101 2102 async def fetch_recuirement_thread_summaries(self) -> typedefs.JSONArray: 2103 resp = await self._request(RequestMethod.POST, "Forum/Recruit/Summaries/") 2104 assert isinstance(resp, list) 2105 return resp 2106 2107 async def fetch_recommended_groups( 2108 self, 2109 accecss_token: str, 2110 /, 2111 *, 2112 date_range: int = 0, 2113 group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN, 2114 ) -> typedefs.JSONArray: 2115 resp = await self._request( 2116 RequestMethod.POST, 2117 f"GroupV2/Recommended/{int(group_type)}/{date_range}/", 2118 auth=accecss_token, 2119 ) 2120 assert isinstance(resp, list) 2121 return resp 2122 2123 async def fetch_available_avatars(self) -> collections.Mapping[str, int]: 2124 resp = await self._request(RequestMethod.GET, "GroupV2/GetAvailableAvatars/") 2125 assert isinstance(resp, dict) 2126 return resp 2127 2128 async def fetch_user_clan_invite_setting( 2129 self, 2130 access_token: str, 2131 /, 2132 membership_type: typedefs.IntAnd[enums.MembershipType], 2133 ) -> bool: 2134 resp = await self._request( 2135 RequestMethod.GET, 2136 f"GroupV2/GetUserClanInviteSetting/{int(membership_type)}/", 2137 auth=access_token, 2138 ) 2139 assert isinstance(resp, bool) 2140 return resp 2141 2142 async def fetch_banned_group_members( 2143 self, access_token: str, group_id: int, /, *, page: int = 1 2144 ) -> typedefs.JSONObject: 2145 resp = await self._request( 2146 RequestMethod.GET, 2147 f"GroupV2/{group_id}/Banned/?currentpage={page}", 2148 auth=access_token, 2149 ) 2150 assert isinstance(resp, dict) 2151 return resp 2152 2153 async def fetch_pending_group_memberships( 2154 self, access_token: str, group_id: int, /, *, current_page: int = 1 2155 ) -> typedefs.JSONObject: 2156 resp = await self._request( 2157 RequestMethod.GET, 2158 f"GroupV2/{group_id}/Members/Pending/?currentpage={current_page}", 2159 auth=access_token, 2160 ) 2161 assert isinstance(resp, dict) 2162 return resp 2163 2164 async def fetch_invited_group_memberships( 2165 self, access_token: str, group_id: int, /, *, current_page: int = 1 2166 ) -> typedefs.JSONObject: 2167 resp = await self._request( 2168 RequestMethod.GET, 2169 f"GroupV2/{group_id}/Members/InvitedIndividuals/?currentpage={current_page}", 2170 auth=access_token, 2171 ) 2172 assert isinstance(resp, dict) 2173 return resp 2174 2175 async def invite_member_to_group( 2176 self, 2177 access_token: str, 2178 /, 2179 group_id: int, 2180 membership_id: int, 2181 membership_type: typedefs.IntAnd[enums.MembershipType], 2182 *, 2183 message: undefined.UndefinedOr[str] = undefined.UNDEFINED, 2184 ) -> typedefs.JSONObject: 2185 resp = await self._request( 2186 RequestMethod.POST, 2187 f"GroupV2/{group_id}/Members/IndividualInvite/{int(membership_type)}/{membership_id}/", 2188 auth=access_token, 2189 json={"message": str(message)}, 2190 ) 2191 assert isinstance(resp, dict) 2192 return resp 2193 2194 async def cancel_group_member_invite( 2195 self, 2196 access_token: str, 2197 /, 2198 group_id: int, 2199 membership_id: int, 2200 membership_type: typedefs.IntAnd[enums.MembershipType], 2201 ) -> typedefs.JSONObject: 2202 resp = await self._request( 2203 RequestMethod.POST, 2204 f"GroupV2/{group_id}/Members/IndividualInviteCancel/{int(membership_type)}/{membership_id}/", 2205 auth=access_token, 2206 ) 2207 assert isinstance(resp, dict) 2208 return resp 2209 2210 async def fetch_historical_definition(self) -> typedefs.JSONObject: 2211 resp = await self._request(RequestMethod.GET, "Destiny2/Stats/Definition/") 2212 assert isinstance(resp, dict) 2213 return resp 2214 2215 async def fetch_historical_stats( 2216 self, 2217 character_id: int, 2218 membership_id: int, 2219 membership_type: typedefs.IntAnd[enums.MembershipType], 2220 day_start: datetime.datetime, 2221 day_end: datetime.datetime, 2222 groups: list[typedefs.IntAnd[enums.StatsGroupType]], 2223 modes: collections.Sequence[typedefs.IntAnd[enums.GameMode]], 2224 *, 2225 period_type: enums.PeriodType = enums.PeriodType.ALL_TIME, 2226 ) -> typedefs.JSONObject: 2227 end, start = time.parse_date_range(day_end, day_start) 2228 resp = await self._request( 2229 RequestMethod.GET, 2230 f"Destiny2/{int(membership_type)}/Account/{membership_id}/Character/{character_id}/Stats/", 2231 json={ 2232 "dayend": end, 2233 "daystart": start, 2234 "groups": [str(int(group)) for group in groups], 2235 "modes": [str(int(mode)) for mode in modes], 2236 "periodType": int(period_type), 2237 }, 2238 ) 2239 assert isinstance(resp, dict) 2240 return resp 2241 2242 async def fetch_historical_stats_for_account( 2243 self, 2244 membership_id: int, 2245 membership_type: typedefs.IntAnd[enums.MembershipType], 2246 groups: list[typedefs.IntAnd[enums.StatsGroupType]], 2247 ) -> typedefs.JSONObject: 2248 resp = await self._request( 2249 RequestMethod.GET, 2250 f"Destiny2/{int(membership_type)}/Account/{membership_id}/Stats/", 2251 json={"groups": [str(int(group)) for group in groups]}, 2252 ) 2253 assert isinstance(resp, dict) 2254 return resp 2255 2256 async def fetch_aggregated_activity_stats( 2257 self, 2258 character_id: int, 2259 membership_id: int, 2260 membership_type: typedefs.IntAnd[enums.MembershipType], 2261 /, 2262 ) -> typedefs.JSONObject: 2263 resp = await self._request( 2264 RequestMethod.GET, 2265 f"Destiny2/{int(membership_type)}/Account/{membership_id}/" 2266 f"Character/{character_id}/Stats/AggregateActivityStats/", 2267 ) 2268 assert isinstance(resp, dict) 2269 return resp 2270 2271 async def equip_loadout( 2272 self, 2273 access_token: str, 2274 /, 2275 loadout_index: int, 2276 character_id: int, 2277 membership_type: typedefs.IntAnd[enums.MembershipType], 2278 ) -> None: 2279 response = await self._request( 2280 RequestMethod.POST, 2281 "Destiny2/Actions/Loadouts/EquipLoadout/", 2282 json={ 2283 "loadoutIndex": loadout_index, 2284 "characterId": character_id, 2285 "membership_type": int(membership_type), 2286 }, 2287 auth=access_token, 2288 ) 2289 assert isinstance(response, int) 2290 2291 async def snapshot_loadout( 2292 self, 2293 access_token: str, 2294 /, 2295 loadout_index: int, 2296 character_id: int, 2297 membership_type: typedefs.IntAnd[enums.MembershipType], 2298 *, 2299 color_hash: typing.Optional[int] = None, 2300 icon_hash: typing.Optional[int] = None, 2301 name_hash: typing.Optional[int] = None, 2302 ) -> None: 2303 response = await self._request( 2304 RequestMethod.POST, 2305 "Destiny2/Actions/Loadouts/SnapshotLoadout/", 2306 auth=access_token, 2307 json={ 2308 "colorHash": color_hash, 2309 "iconHash": icon_hash, 2310 "nameHash": name_hash, 2311 "loadoutIndex": loadout_index, 2312 "characterId": character_id, 2313 "membershipType": int(membership_type), 2314 }, 2315 ) 2316 assert isinstance(response, int) 2317 2318 async def update_loadout( 2319 self, 2320 access_token: str, 2321 /, 2322 loadout_index: int, 2323 character_id: int, 2324 membership_type: typedefs.IntAnd[enums.MembershipType], 2325 *, 2326 color_hash: typing.Optional[int] = None, 2327 icon_hash: typing.Optional[int] = None, 2328 name_hash: typing.Optional[int] = None, 2329 ) -> None: 2330 response = await self._request( 2331 RequestMethod.POST, 2332 "Destiny2/Actions/Loadouts/UpdateLoadoutIdentifiers/", 2333 auth=access_token, 2334 json={ 2335 "colorHash": color_hash, 2336 "iconHash": icon_hash, 2337 "nameHash": name_hash, 2338 "loadoutIndex": loadout_index, 2339 "characterId": character_id, 2340 "membershipType": int(membership_type), 2341 }, 2342 ) 2343 assert isinstance(response, int) 2344 2345 async def clear_loadout( 2346 self, 2347 access_token: str, 2348 /, 2349 loadout_index: int, 2350 character_id: int, 2351 membership_type: typedefs.IntAnd[enums.MembershipType], 2352 ) -> None: 2353 response = await self._request( 2354 RequestMethod.POST, 2355 "Destiny2/Actions/Loadouts/ClearLoadout/", 2356 json={ 2357 "loadoutIndex": loadout_index, 2358 "characterId": character_id, 2359 "membership_type": int(membership_type), 2360 }, 2361 auth=access_token, 2362 ) 2363 assert isinstance(response, int)
A RESTful client implementation for Bungie's API.
This client is designed to only make HTTP requests and return JSON objects to provide RESTful functionality.
This client is also used within aiobungie.Client which deserialize those returned JSON objects
using the factory into Pythonic data classes objects which provide Python functionality.
Example
import aiobungie
async def main():
async with aiobungie.RESTClient("TOKEN") as rest_client:
req = await rest_client.fetch_clan_members(4389205)
clan_members = req['results']
for member in clan_members:
for k, v in member['destinyUserInfo'].items():
print(k, v)
Parameters
- token (
str): A valid application token from Bungie's developer portal.
Other Parameters
- max_retries (
int): The max retries number to retry if the request hit a5xxstatus code. - client_secret (
typing.Optional[str]): An optional application client secret, This is only needed if you're fetching OAuth2 tokens with this client. - client_id (
typing.Optional[int]): An optional application client id, This is only needed if you're fetching OAuth2 tokens with this client. - enable_debugging (
bool | str): Whether to enable logging responses or not.
Logging Levels
False: This will disable logging.True: This will set the level toDEBUGand enable logging minimal information."TRACE" | TRACE: This will log the response headers along with the minimal information.
371 def __init__( 372 self, 373 token: str, 374 /, 375 *, 376 client_secret: typing.Optional[str] = None, 377 client_id: typing.Optional[int] = None, 378 client_session: typing.Optional[aiohttp.ClientSession] = None, 379 max_retries: int = 4, 380 enable_debugging: typing.Union[typing.Literal["TRACE"], bool, int] = False, 381 ) -> None: 382 self._session: typing.Optional[aiohttp.ClientSession] = client_session 383 self._lock: typing.Optional[asyncio.Lock] = None 384 self._client_secret = client_secret 385 self._client_id = client_id 386 self._token: str = token 387 self._max_retries = max_retries 388 self._metadata: collections.MutableMapping[typing.Any, typing.Any] = {} 389 390 self._set_debug_level(enable_debugging)
A mutable mapping storage for the user's needs.
This mapping is useful for storing any kind of data that the user may need.
Example
import aiobungie
client = aiobungie.RESTClient(…)
async with client:
# Fetch auth tokens and store them
client.metadata["tokens"] = await client.fetch_access_token("code")
# Some other time.
async with client:
# Retrieve the tokens
tokens: aiobungie.OAuth2Response = client.metadata["tokens"]
# Use them to fetch your user.
user = await client.fetch_current_user_memberships(tokens.access_token)
404 @typing.final 405 async def close(self) -> None: 406 if self._session is None: 407 raise RuntimeError("REST client is not running.") 408 409 await self._session.close() 410 self._session = None
Close this REST client session if it was acquired.
This method is automatically called when using async with contextmanager.
Raises
RuntimeError: If the client is already closed.
412 @typing.final 413 def open(self) -> None: 414 """Open a new client session. This is called internally with contextmanager usage.""" 415 if self._session: 416 raise RuntimeError("Cannot open REST client when it's already open.") 417 418 self._session = aiohttp.ClientSession( 419 connector=aiohttp.TCPConnector(ssl=False), 420 raise_for_status=False, 421 timeout=aiohttp.ClientTimeout(total=30.0), 422 )
Open a new client session. This is called internally with contextmanager usage.
424 @typing.final 425 def enable_debugging( 426 self, 427 level: typing.Union[typing.Literal["TRACE"], bool, int] = False, 428 file: typing.Optional[typing.Union[pathlib.Path, str]] = None, 429 /, 430 ) -> None: 431 self._set_debug_level(level, file)
Enables debugging for the REST calls.
Logging Levels
False: This will disable logging.True: This will set the level toDEBUGand enable logging minimal information."TRACE"|TRACE: This will log the response headers along with the minimal information.
Parameters
- level (
str | bool | int): The level of debugging to enable. - file (
pathlib.Path | str | None): The file path to write the debug logs to. If provided.
433 @typing.final 434 async def static_request( 435 self, 436 method: typing.Union[RequestMethod, str], 437 path: str, 438 *, 439 auth: typing.Optional[str] = None, 440 json: typing.Optional[dict[str, typing.Any]] = None, 441 ) -> ResponseSig: 442 return await self._request(method, path, auth=auth, json=json)
Perform an HTTP request given a valid Bungie endpoint.
Parameters
- method (
RequestMethod | str): The request method, This may beGET,POST,PUT, etc. - path (
str): The Bungie endpoint or path. A path must look something like thisDestiny2/3/Profile/46111239123/... - auth (
str | None): An optional bearer token for methods that requires OAuth2 Authorization header. - json (
dict[str, typing.Any] | None): An optional JSON data to include in the request.
Returns
aiobungie.rest.ResponseSig: The response payload.
444 @typing.final 445 def build_oauth2_url( 446 self, client_id: typing.Optional[int] = None 447 ) -> typing.Optional[builders.OAuthURL]: 448 client_id = client_id or self._client_id 449 if client_id is None: 450 return None 451 452 return builders.OAuthURL(client_id=client_id)
Builds an OAuth2 URL using the provided user REST/Base client secret/id.
You can't get the complete string URL by using .compile() method.
Parameters
- client_id (
int | None): An optional client id to provide, If leftNoneit will roll back to the id passed to theRESTClient, If both isNonethis method will returnNone.
Returns
aiobungie.builders.OAuthURL | None: If the client id was provided as a parameter or provided inaiobungie.RESTClient, A complete OAuthURL object will be returned. OtherwiseNonewill be returned.
660 async def fetch_oauth2_tokens(self, code: str, /) -> builders.OAuth2Response: 661 if not isinstance(self._client_secret, (str, int)): 662 raise TypeError( 663 "Expected (str, int) for client secret " 664 f"but got {type(self._client_secret).__name__}" # type: ignore 665 ) 666 667 headers = { 668 "client_secret": self._client_secret, 669 } 670 671 data = ( 672 f"grant_type=authorization_code&code={code}" 673 f"&client_id={self._client_id}&client_secret={self._client_secret}" 674 ) 675 676 response = await self._request( 677 RequestMethod.POST, "", headers=headers, data=data, oauth2=True 678 ) 679 assert isinstance(response, dict) 680 return builders.OAuth2Response.build_response(response)
Makes a POST request and fetch the OAuth2 access_token and refresh token.
Parameters
- code (
str): The Authorization code received from the authorization endpoint found in the URL parameters.
Returns
aiobungie.builders.OAuth2Response: An OAuth2 deserialized response.
Raises
Unauthorized: The passed code was invalid.
682 async def refresh_access_token( 683 self, refresh_token: str, / 684 ) -> builders.OAuth2Response: 685 if not isinstance(self._client_secret, (int, str)): 686 raise TypeError( 687 f"Expected (str, int) for client secret but got {type(self._client_secret).__name__}" # type: ignore 688 ) 689 690 data = { 691 "grant_type": "refresh_token", 692 "refresh_token": refresh_token, 693 "client_id": self._client_id, 694 "client_secret": self._client_secret, 695 "Content-Type": "application/x-www-form-urlencoded", 696 } 697 698 response = await self._request(RequestMethod.POST, "", data=data, oauth2=True) 699 assert isinstance(response, dict) 700 return builders.OAuth2Response.build_response(response)
Refresh OAuth2 access token given its refresh token.
Parameters
- refresh_token (
str): The refresh token.
Returns
aiobungie.builders.OAuth2Response: An OAuth2 deserialized response.
702 async def fetch_bungie_user(self, id: int) -> typedefs.JSONObject: 703 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 704 resp = await self._request( 705 RequestMethod.GET, f"User/GetBungieNetUserById/{id}/" 706 ) 707 assert isinstance(resp, dict) 708 return resp
Fetch a Bungie user by their id.
Parameters
- id (
int): The user id.
Returns
aiobungie.typedefs.JSONObject: A JSON object of users objects.
Raises
NotFound: The user was not found.
716 async def fetch_membership_from_id( 717 self, 718 id: int, 719 type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE, 720 /, 721 ) -> typedefs.JSONObject: 722 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 723 resp = await self._request( 724 RequestMethod.GET, f"User/GetMembershipsById/{id}/{int(type)}" 725 ) 726 assert isinstance(resp, dict) 727 return resp
Fetch Bungie user's memberships from their id.
Parameters
- id (
int): The user's id. - type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The user's membership type.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the found user.
Raises
- aiobungie.NotFound: The requested user was not found.
729 async def fetch_player( 730 self, 731 name: str, 732 code: int, 733 type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.ALL, 734 /, 735 ) -> typedefs.JSONArray: 736 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 737 resp = await self._request( 738 RequestMethod.POST, 739 f"Destiny2/SearchDestinyPlayerByBungieName/{int(type)}", 740 json={"displayName": name, "displayNameCode": code}, 741 ) 742 assert isinstance(resp, list) 743 return resp
Fetch a Destiny 2 Player.
Parameters
- name (
str): The unique Bungie player name. - code (
int): The unique Bungie display name code. - type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The player's membership type, e,g. XBOX, STEAM, PSN
Returns
aiobungie.typedefs.JSONArray: A JSON array of the found player's memberships.
Raises
aiobungie.NotFound: The player was not found.aiobungie.MembershipTypeError: The provided membership type was invalid.
745 async def search_users(self, name: str, /) -> typedefs.JSONObject: 746 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 747 resp = await self._request( 748 RequestMethod.POST, 749 "User/Search/GlobalName/0", 750 json={"displayNamePrefix": name}, 751 ) 752 assert isinstance(resp, dict) 753 return resp
Search for users by their global name and return all users who share this name.
Parameters
- name (
str): The user name.
Returns
aiobungie.typedefs.JSONObject: A JSON object of an array of the found users.
Raises
aiobungie.NotFound: The user(s) was not found.
755 async def fetch_clan_from_id( 756 self, id: int, /, access_token: typing.Optional[str] = None 757 ) -> typedefs.JSONObject: 758 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 759 resp = await self._request( 760 RequestMethod.GET, f"GroupV2/{id}", auth=access_token 761 ) 762 assert isinstance(resp, dict) 763 return resp
Fetch a Bungie Clan by its id.
Parameters
- id (
int): The clan id.
Other Parameters
access_token (
typing.Optional[str]): An optional access token to make the request with.If the token was bound to a member of the clan, This field
aiobungie.crates.Clan.current_user_membershipwill be available and will return the membership of the user who made this request.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the clan.
Raises
aiobungie.NotFound: The clan was not found.
765 async def fetch_clan( 766 self, 767 name: str, 768 /, 769 access_token: typing.Optional[str] = None, 770 *, 771 type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN, 772 ) -> typedefs.JSONObject: 773 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 774 resp = await self._request( 775 RequestMethod.GET, f"GroupV2/Name/{name}/{int(type)}", auth=access_token 776 ) 777 assert isinstance(resp, dict) 778 return resp
Fetch a Clan by its name. This method will return the first clan found with given name name.
Parameters
- name (
str): The clan name.
Other Parameters
access_token (
typing.Optional[str]): An optional access token to make the request with.If the token was bound to a member of the clan, This field
aiobungie.crates.Clan.current_user_membershipwill be available and will return the membership of the user who made this request.- type (
aiobungie.typedefs.IntAnd[aiobungie.GroupType]): The group type, Default is one.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the clan.
Raises
aiobungie.NotFound: The clan was not found.
780 async def fetch_clan_admins(self, clan_id: int, /) -> typedefs.JSONObject: 781 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 782 resp = await self._request( 783 RequestMethod.GET, f"GroupV2/{clan_id}/AdminsAndFounder/" 784 ) 785 assert isinstance(resp, dict) 786 return resp
Fetch the admins and founder members of the clan.
Parameters
- clan_id (
int): The clan id.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the clan admins and founder members.
Raises
aiobungie.NotFound: The clan was not found.
788 async def fetch_clan_conversations(self, clan_id: int, /) -> typedefs.JSONArray: 789 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 790 resp = await self._request( 791 RequestMethod.GET, f"GroupV2/{clan_id}/OptionalConversations/" 792 ) 793 assert isinstance(resp, list) 794 return resp
Fetch a clan's conversations.
Parameters
- clan_id (
int): The clan's id.
Returns
aiobungie.typedefs.JSONArray: A JSON array of the conversations.
796 async def fetch_application(self, appid: int, /) -> typedefs.JSONObject: 797 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 798 resp = await self._request(RequestMethod.GET, f"App/Application/{appid}") 799 assert isinstance(resp, dict) 800 return resp
Fetch a Bungie Application.
Parameters
- appid (
int): The application id.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the application.
802 async def fetch_character( 803 self, 804 member_id: int, 805 membership_type: typedefs.IntAnd[enums.MembershipType], 806 character_id: int, 807 components: list[enums.ComponentType], 808 auth: typing.Optional[str] = None, 809 ) -> typedefs.JSONObject: 810 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 811 collector = _collect_components(components) 812 response = await self._request( 813 RequestMethod.GET, 814 f"Destiny2/{int(membership_type)}/Profile/{member_id}/" 815 f"Character/{character_id}/?components={collector}", 816 auth=auth, 817 ) 818 assert isinstance(response, dict) 819 return response
Fetch a Destiny 2 player's characters.
Parameters
- member_id (
int): A valid bungie member id. - membership_type (
aiobungie.typedefs.IntAnd[MembershipType]): The member's membership type. - character_id (
int): The character id to return. - components (
list[aiobungie.ComponentType]): A list of character components to collect and return.
Other Parameters
- auth (
typing.Optional[str]): A bearer access_token to make the request with. This is optional and limited to components that only requires an Authorization token.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the requested character.
Raises
aiobungie.MembershipTypeError: The provided membership type was invalid.
821 async def fetch_activities( 822 self, 823 member_id: int, 824 character_id: int, 825 mode: typedefs.IntAnd[enums.GameMode], 826 membership_type: typedefs.IntAnd[ 827 enums.MembershipType 828 ] = enums.MembershipType.ALL, 829 *, 830 page: int = 0, 831 limit: int = 1, 832 ) -> typedefs.JSONObject: 833 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 834 resp = await self._request( 835 RequestMethod.GET, 836 f"Destiny2/{int(membership_type)}/Account/" 837 f"{member_id}/Character/{character_id}/Stats/Activities" 838 f"/?mode={int(mode)}&count={limit}&page={page}", 839 ) 840 assert isinstance(resp, dict) 841 return resp
Fetch a Destiny 2 activity for the specified user id and character.
Parameters
- member_id (
int): The user id that starts with4611. - character_id (
int): The id of the character to retrieve. - mode (
aiobungie.typedefs.IntAnd[aiobungie.GameMode]): This parameter filters the game mode, Nightfall, Strike, Iron Banner, etc.
Other Parameters
- membership_type (
aiobungie.typedefs.IntAnd[MembershipType]): The Member ship type, if nothing was passed than it will return all. - page (
int): The page number. Default to1 - limit (
int): Limit the returned result. Default to1
Returns
aiobungie.typedefs.JSONObject: A JSON object of the player's activities.
Raises
NotFound: The activity was not found.aiobungie.MembershipTypeError: The provided membership type was invalid.
843 async def fetch_vendor_sales(self) -> typedefs.JSONObject: 844 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 845 resp = await self._request( 846 RequestMethod.GET, 847 f"Destiny2/Vendors/?components={int(enums.ComponentType.VENDOR_SALES)}", 848 ) 849 assert isinstance(resp, dict) 850 return resp
852 async def fetch_profile( 853 self, 854 membership_id: int, 855 type: typedefs.IntAnd[enums.MembershipType], 856 components: list[enums.ComponentType], 857 auth: typing.Optional[str] = None, 858 ) -> typedefs.JSONObject: 859 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 860 collector = _collect_components(components) 861 response = await self._request( 862 RequestMethod.GET, 863 f"Destiny2/{int(type)}/Profile/{membership_id}/?components={collector}", 864 auth=auth, 865 ) 866 assert isinstance(response, dict) 867 return response
Fetch a bungie profile.
Parameters
- membership_id (
int): The member's id. - type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): A valid membership type. - components (
list[aiobungie.ComponentType]): A list of profile components to collect and return.
Other Parameters
- auth (
typing.Optional[str]): A bearer access_token to make the request with. This is optional and limited to components that only requires an Authorization token.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the found profile.
Raises
aiobungie.MembershipTypeError: The provided membership type was invalid.
869 async def fetch_entity(self, type: str, hash: int) -> typedefs.JSONObject: 870 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 871 response = await self._request( 872 RequestMethod.GET, route=f"Destiny2/Manifest/{type}/{hash}" 873 ) 874 assert isinstance(response, dict) 875 return response
Fetch a Destiny definition item given its type and hash.
Parameters
- type (
str): Entity's type definition. - hash (
int): Entity's hash.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the definition data.
877 async def fetch_inventory_item(self, hash: int, /) -> typedefs.JSONObject: 878 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 879 resp = await self.fetch_entity("DestinyInventoryItemDefinition", hash) 880 assert isinstance(resp, dict) 881 return resp
Fetch a Destiny inventory item entity given a its hash.
Parameters
- hash (
int): Entity's hash.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the inventory item.
883 async def fetch_objective_entity(self, hash: int, /) -> typedefs.JSONObject: 884 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 885 resp = await self.fetch_entity("DestinyObjectiveDefinition", hash) 886 assert isinstance(resp, dict) 887 return resp
Fetch a Destiny objective entity given a its hash.
Parameters
- hash (
int): objective's hash.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the objetive data.
889 async def fetch_groups_for_member( 890 self, 891 member_id: int, 892 member_type: typedefs.IntAnd[enums.MembershipType], 893 /, 894 *, 895 filter: int = 0, 896 group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN, 897 ) -> typedefs.JSONObject: 898 resp = await self._request( 899 RequestMethod.GET, 900 f"GroupV2/User/{int(member_type)}/{member_id}/{filter}/{int(group_type)}/", 901 ) 902 assert isinstance(resp, dict) 903 return resp
Fetch the information about the groups for a member.
Parameters
- member_id (
int): The member's id - member_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The member's membership type.
Other Parameters
- filter (
builsins.int): Filter apply to list of joined groups. This Default to0 - group_type (
aiobungie.typedefs.IntAnd[aiobungie.GroupType]): The group's type. This is always set toaiobungie.GroupType.CLANand should not be changed.
Returns
aiobungie.typedefs.JSONObject: A JSON object of an array of the member's membership data and groups data.
905 async def fetch_potential_groups_for_member( 906 self, 907 member_id: int, 908 member_type: typedefs.IntAnd[enums.MembershipType], 909 /, 910 *, 911 filter: int = 0, 912 group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN, 913 ) -> typedefs.JSONObject: 914 resp = await self._request( 915 RequestMethod.GET, 916 f"GroupV2/User/Potential/{int(member_type)}/{member_id}/{filter}/{int(group_type)}/", 917 ) 918 assert isinstance(resp, dict) 919 return resp
Get information about the groups that a given member has applied to or been invited to.
Parameters
- member_id (
int): The member's id - member_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The member's membership type.
Other Parameters
- filter (
builsins.int): Filter apply to list of joined groups. This Default to0 - group_type (
aiobungie.typedefs.IntAnd[aiobungie.GroupType]): The group's type. This is always set toaiobungie.GroupType.CLANand should not be changed.
Returns
aiobungie.typedefs.JSONObject: A JSON object of an array of the member's membership data and groups data.
921 async def fetch_clan_members( 922 self, 923 clan_id: int, 924 /, 925 *, 926 name: typing.Optional[str] = None, 927 type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE, 928 ) -> typedefs.JSONObject: 929 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 930 resp = await self._request( 931 RequestMethod.GET, 932 f"/GroupV2/{clan_id}/Members/?memberType={int(type)}&nameSearch={name if name else ''}¤tpage=1", 933 ) 934 assert isinstance(resp, dict) 935 return resp
Fetch all Bungie Clan members.
Parameters
- clan_id (
builsins.int): The clans id
Other Parameters
- name (
typing.Optional[str]): If provided, Only players matching this name will be returned. - type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): An optional clan member's membership type. Default is set toaiobungie.MembershipType.NONEWhich returns the first matched clan member by their name.
Returns
aiobungie.typedefs.JSONObject: A JSON object of an array of clan members.
Raises
aiobungie.NotFound: The clan was not found.
937 async def fetch_hardlinked_credentials( 938 self, 939 credential: int, 940 type: typedefs.IntAnd[enums.CredentialType] = enums.CredentialType.STEAMID, 941 /, 942 ) -> typedefs.JSONObject: 943 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 944 resp = await self._request( 945 RequestMethod.GET, 946 f"User/GetMembershipFromHardLinkedCredential/{int(type)}/{credential}/", 947 ) 948 assert isinstance(resp, dict) 949 return resp
Gets any hard linked membership given a credential.
Only works for credentials that are public just aiobungie.CredentialType.STEAMID right now.
Cross Save aware.
Parameters
- credential (
int): A valid SteamID64 - type (
aiobungie.typedefs.IntAnd[aiobungie.CredentialType]): The crededntial type. This must not be changed Since its only credential that works "currently"
Returns
aiobungie.typedefs.JSONObject: A JSON object of the found user hard linked types.
951 async def fetch_user_credentials( 952 self, access_token: str, membership_id: int, / 953 ) -> typedefs.JSONArray: 954 resp = await self._request( 955 RequestMethod.GET, 956 f"User/GetCredentialTypesForTargetAccount/{membership_id}", 957 auth=access_token, 958 ) 959 assert isinstance(resp, list) 960 return resp
Fetch an array of credential types attached to the requested account.
This method require OAuth2 Bearer access token.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - membership_id (
int): The id of the membership to return.
Returns
aiobungie.typedefs.JSONArray: A JSON array of the returned credentials.
Raises
aiobungie.Unauthorized: The access token was wrong or no access token passed.
962 async def insert_socket_plug( 963 self, 964 action_token: str, 965 /, 966 instance_id: int, 967 plug: typing.Union[builders.PlugSocketBuilder, dict[str, int]], 968 character_id: int, 969 membership_type: typedefs.IntAnd[enums.MembershipType], 970 ) -> typedefs.JSONObject: 971 if isinstance(plug, builders.PlugSocketBuilder): 972 plug = plug.collect() 973 974 body = { 975 "actionToken": action_token, 976 "itemInstanceId": instance_id, 977 "plug": plug, 978 "characterId": character_id, 979 "membershipType": int(membership_type), 980 } 981 resp = await self._request( 982 RequestMethod.POST, "Destiny2/Actions/Items/InsertSocketPlug", json=body 983 ) 984 assert isinstance(resp, dict) 985 return resp
Insert a plug into a socketed item.
OAuth2: AdvancedWriteActions scope is required
Parameters
- action_token (
str): Action token provided by the AwaGetActionToken API call. - instance_id (
int): The item instance id that's plug inserted. - plug (
typing.Union[aiobungie.builders.PlugSocketBuilder, dict[str, int]]): Either a PlugSocketBuilder object or a raw dict contains key, value for the plug entries.
Example
plug = (
aiobungie.PlugSocketBuilder()
.set_socket_array(0)
.set_socket_index(0)
.set_plug_item(3023847)
.collect()
)
await insert_socket_plug_free(..., plug=plug)
character_id : int
The character's id.
membership_type : aiobungie.typedefs.IntAnd[aiobungie.MembershipType]
The membership type.
Returns
aiobungie.typedefs.JSONObject: A JSON object contains the changed item details.
Raises
aiobungie.Unauthorized: The access token was wrong or no access token passed.
987 async def insert_socket_plug_free( 988 self, 989 access_token: str, 990 /, 991 instance_id: int, 992 plug: typing.Union[builders.PlugSocketBuilder, dict[str, int]], 993 character_id: int, 994 membership_type: typedefs.IntAnd[enums.MembershipType], 995 ) -> typedefs.JSONObject: 996 if isinstance(plug, builders.PlugSocketBuilder): 997 plug = plug.collect() 998 999 body = { 1000 "itemInstanceId": instance_id, 1001 "plug": plug, 1002 "characterId": character_id, 1003 "membershipType": int(membership_type), 1004 } 1005 resp = await self._request( 1006 RequestMethod.POST, 1007 "Destiny2/Actions/Items/InsertSocketPlugFree", 1008 json=body, 1009 auth=access_token, 1010 ) 1011 assert isinstance(resp, dict) 1012 return resp
Insert a plug into a socketed item. This doesn't require an Action token.
OAuth2: MoveEquipDestinyItems scope is required
Parameters
- instance_id (
int): The item instance id that's plug inserted. - plug (
typing.Union[aiobungie.builders.PlugSocketBuilder, dict[str, int]]): Either a PlugSocketBuilder object or a raw dict contains key, value for the plug entries.
Example
plug = (
aiobungie.PlugSocketBuilder()
.set_socket_array(0)
.set_socket_index(0)
.set_plug_item(3023847)
.collect()
)
await insert_socket_plug_free(..., plug=plug)
character_id : int
The character's id.
membership_type : aiobungie.typedefs.IntAnd[aiobungie.MembershipType]
The membership type.
Returns
aiobungie.typedefs.JSONObject: A JSON object contains the changed item details.
Raises
aiobungie.Unauthorized: The access token was wrong or no access token passed.
1014 async def set_item_lock_state( 1015 self, 1016 access_token: str, 1017 state: bool, 1018 /, 1019 item_id: int, 1020 character_id: int, 1021 membership_type: typedefs.IntAnd[enums.MembershipType], 1022 ) -> int: 1023 body = { 1024 "state": state, 1025 "itemId": item_id, 1026 "characterId": character_id, 1027 "membershipType": int(membership_type), 1028 } 1029 response = await self._request( 1030 RequestMethod.POST, 1031 "Destiny2/Actions/Items/SetLockState", 1032 json=body, 1033 auth=access_token, 1034 ) 1035 assert isinstance(response, int) 1036 return response
Set the Lock State for an instanced item.
OAuth2: MoveEquipDestinyItems scope is required
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - state (
bool): IfTrue, The item will be locked, IfFalse, The item will be unlocked. - item_id (
int): The item id. - character_id (
int): The character id. - membership_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The membership type for the associated account.
Returns
int: An integer represents whether the request was successful or failed.
Raises
aiobungie.Unauthorized: - The access token was wrong- No access token passed.
- Other authorization causes.
1038 async def set_quest_track_state( 1039 self, 1040 access_token: str, 1041 state: bool, 1042 /, 1043 item_id: int, 1044 character_id: int, 1045 membership_type: typedefs.IntAnd[enums.MembershipType], 1046 ) -> int: 1047 body = { 1048 "state": state, 1049 "itemId": item_id, 1050 "characterId": character_id, 1051 "membership_type": int(membership_type), 1052 } 1053 response = await self._request( 1054 RequestMethod.POST, 1055 "Destiny2/Actions/Items/SetTrackedState", 1056 json=body, 1057 auth=access_token, 1058 ) 1059 assert isinstance(response, int) 1060 return response
Set the Tracking State for an instanced Quest or Bounty.
OAuth2: MoveEquipDestinyItems scope is required
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - state (
bool): IfTrue, The item will be locked, IfFalse, The item will be unlocked. - item_id (
int): The item id. - character_id (
int): The character id. - membership_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The membership type for the associated account.
Returns
int: An integer represents whether the request was successful or failed.
Raises
aiobungie.Unauthorized: - The access token was wrong- No access token passed.
- Other authorization causes.
1062 async def fetch_manifest_path(self) -> typedefs.JSONObject: 1063 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1064 path = await self._request(RequestMethod.GET, "Destiny2/Manifest") 1065 assert isinstance(path, dict) 1066 return path
Fetch the manifest JSON paths.
Returns
typedefs.JSONObject: The manifest JSON paths.
1068 async def read_manifest_bytes(self, language: str = "en", /) -> bytes: 1069 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1070 _ensure_manifest_language(language) 1071 1072 content = await self.fetch_manifest_path() 1073 resp = await self._request( 1074 RequestMethod.GET, 1075 content["mobileWorldContentPaths"][language], 1076 unwrapping="read", 1077 base=True, 1078 ) 1079 assert isinstance(resp, bytes) 1080 return resp
Read raw manifest SQLite database bytes response.
This method can be used to write the bytes to zipped file and then extract it to get the manifest content.
Parameters
- language (
str): The manifest database language bytes to get.
Returns
bytes: The bytes to read and write the manifest database.
1082 async def download_manifest( 1083 self, 1084 language: str = "en", 1085 name: str = "manifest", 1086 path: typing.Union[pathlib.Path, str] = ".", 1087 *, 1088 force: bool = False, 1089 ) -> None: 1090 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1091 complete_path = _get_path(name, path, sql=True) 1092 1093 if complete_path.exists() and force: 1094 if force: 1095 _LOG.info( 1096 f"Found manifest in {complete_path!s}. Forcing to Re-Download." 1097 ) 1098 complete_path.unlink(missing_ok=True) 1099 1100 return await self.download_manifest(language, name, path, force=force) 1101 1102 else: 1103 raise FileExistsError( 1104 "Manifest file already exists, " 1105 "To force download, set the `force` parameter to `True`." 1106 ) 1107 1108 _LOG.info(f"Downloading manifest. Location: {complete_path!s}") 1109 data_bytes = await self.read_manifest_bytes(language) 1110 await asyncio.get_running_loop().run_in_executor( 1111 None, _write_sqlite_bytes, data_bytes, path, name 1112 )
A helper method to download the manifest.
Note
This method downloads the sqlite database and not JSON.
Use RESTInterface.download_json_manifest for the JSON version.
Parameters
- language (
str): The manifest language to download, Default is english. - path (
str|pathlib.Path): The path to save the manifest sqlite database. Example"D:/", Default is the current directory. - name (
str): The manifest database file name. Default ismanifest - force (
bool): Whether to force the download. Default isFalse. However if set to true the old file will get removed and a new one will being to download.
Returns
None
Raises
FileNotFoundError: If the manifest file exists andforceisFalse.ValueError: If the provided language was not recognized.
1114 async def download_json_manifest( 1115 self, 1116 file_name: str = "manifest", 1117 path: typing.Union[str, pathlib.Path] = ".", 1118 language: str = "en", 1119 ) -> None: 1120 _ensure_manifest_language(language) 1121 1122 _LOG.info(f"Downloading manifest JSON to {_get_path(file_name, path)!r}...") 1123 1124 content = await self.fetch_manifest_path() 1125 json_bytes = await self._request( 1126 RequestMethod.GET, 1127 content["jsonWorldContentPaths"][language], 1128 unwrapping="read", 1129 base=True, 1130 ) 1131 1132 await asyncio.get_running_loop().run_in_executor( 1133 None, _write_json_bytes, json_bytes, file_name, path 1134 ) 1135 _LOG.info("Finished downloading manifest JSON.")
Download the Bungie manifest json file.
Parameters
- file_name (
str): The file name to save the manifest json file. Default ismanifest. - path (
str|pathlib.Path): The path to save the manifest json file. Default is the current directory. Example"D:/" - language (
str): The manifest database language bytes to get. Default is English.
1137 async def fetch_manifest_version(self) -> str: 1138 return typing.cast(str, (await self.fetch_manifest_path())["version"])
Fetch the manifest version.
Returns
str: The manifest version.
1140 async def fetch_linked_profiles( 1141 self, 1142 member_id: int, 1143 member_type: typedefs.IntAnd[enums.MembershipType], 1144 /, 1145 *, 1146 all: bool = False, 1147 ) -> typedefs.JSONObject: 1148 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1149 resp = await self._request( 1150 RequestMethod.GET, 1151 f"Destiny2/{int(member_type)}/Profile/{member_id}/LinkedProfiles/?getAllMemberships={all}", 1152 ) 1153 assert isinstance(resp, dict) 1154 return resp
Returns a summary information about all profiles linked to the requested member.
The passed membership id/type maybe a Bungie.Net membership or a Destiny memberships.
It will only return linked accounts whose linkages you are allowed to view.
Parameters
- member_id (
int): The ID of the membership. This must be a valid Bungie.Net or PSN or Xbox ID. - member_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The type for the membership whose linked Destiny account you want to return.
Other Parameters
all (
bool): If provided and set toTrue, All memberships regardless of whether thry're obscured by overrides will be returned,If provided and set to
False, Only available memberships will be returned. The default for this isFalse.
Returns
aiobungie.typedefs.JSONObject- A JSON object which contains an Array of profiles, an Array of profiles with errors and Bungie.Net membership
1164 async def fetch_public_milestones(self) -> typedefs.JSONObject: 1165 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1166 resp = await self._request(RequestMethod.GET, "Destiny2/Milestones/") 1167 assert isinstance(resp, dict) 1168 return resp
Fetch the available milestones.
Returns
aiobungie.typedefs.JSONObject: A JSON object of information about the milestones.
1170 async def fetch_public_milestone_content( 1171 self, milestone_hash: int, / 1172 ) -> typedefs.JSONObject: 1173 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1174 resp = await self._request( 1175 RequestMethod.GET, f"Destiny2/Milestones/{milestone_hash}/Content/" 1176 ) 1177 assert isinstance(resp, dict) 1178 return resp
Fetch the milestone content given its hash.
Parameters
- milestone_hash (
int): The milestone hash.
Returns
aiobungie.typedefs.JSONObject: A JSON object of information related to the fetched milestone.
1180 async def fetch_current_user_memberships( 1181 self, access_token: str, / 1182 ) -> typedefs.JSONObject: 1183 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1184 resp = await self._request( 1185 RequestMethod.GET, 1186 "User/GetMembershipsForCurrentUser/", 1187 auth=access_token, 1188 ) 1189 assert isinstance(resp, dict) 1190 return resp
Fetch a bungie user's accounts with the signed in user. This GET method requires a Bearer access token for the authorization.
This requires OAuth2 scope enabled and the valid Bearer access_token.
Parameters
- access_token (
str): The bearer access token associated with the bungie account.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the bungie net user and destiny memberships of this account.
1192 async def equip_item( 1193 self, 1194 access_token: str, 1195 /, 1196 item_id: int, 1197 character_id: int, 1198 membership_type: typedefs.IntAnd[enums.MembershipType], 1199 ) -> None: 1200 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1201 payload = { 1202 "itemId": item_id, 1203 "characterId": character_id, 1204 "membershipType": int(membership_type), 1205 } 1206 1207 await self._request( 1208 RequestMethod.POST, 1209 "Destiny2/Actions/Items/EquipItem/", 1210 json=payload, 1211 auth=access_token, 1212 )
Equip an item to a character.
This requires the OAuth2: MoveEquipDestinyItems scope. Also You must have a valid Destiny account, and either be in a social space, in orbit or offline.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - item_id (
int): The item id. - character_id (
int): The character's id to equip the item to. - membership_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The membership type assocaiated with this player.
1214 async def equip_items( 1215 self, 1216 access_token: str, 1217 /, 1218 item_ids: list[int], 1219 character_id: int, 1220 membership_type: typedefs.IntAnd[enums.MembershipType], 1221 ) -> None: 1222 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1223 payload = { 1224 "itemIds": item_ids, 1225 "characterId": character_id, 1226 "membershipType": int(membership_type), 1227 } 1228 await self._request( 1229 RequestMethod.POST, 1230 "Destiny2/Actions/Items/EquipItems/", 1231 json=payload, 1232 auth=access_token, 1233 )
Equip multiple items to a character.
This requires the OAuth2: MoveEquipDestinyItems scope. Also You must have a valid Destiny account, and either be in a social space, in orbit or offline.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - item_ids (
list[int]): A list of item ids. - character_id (
int): The character's id to equip the item to. - membership_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The membership type assocaiated with this player.
1235 async def ban_clan_member( 1236 self, 1237 access_token: str, 1238 /, 1239 group_id: int, 1240 membership_id: int, 1241 membership_type: typedefs.IntAnd[enums.MembershipType], 1242 *, 1243 length: int = 0, 1244 comment: undefined.UndefinedOr[str] = undefined.UNDEFINED, 1245 ) -> None: 1246 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1247 payload = {"comment": str(comment), "length": length} 1248 await self._request( 1249 RequestMethod.POST, 1250 f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Ban/", 1251 json=payload, 1252 auth=access_token, 1253 )
Bans a member from the clan.
This request requires OAuth2: oauth2: AdminGroups scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - group_id (
int): The group id. - membership_id (
int): The member id to ban. - membership_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The member's membership type.
Other Parameters
- length (
int): An optional ban length. - comment (
aiobungie.UndefinedOr[str]): An optional comment to this ban. Default isUNDEFINED
1255 async def unban_clan_member( 1256 self, 1257 access_token: str, 1258 /, 1259 group_id: int, 1260 membership_id: int, 1261 membership_type: typedefs.IntAnd[enums.MembershipType], 1262 ) -> None: 1263 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1264 await self._request( 1265 RequestMethod.POST, 1266 f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Unban/", 1267 auth=access_token, 1268 )
Unbans a member from the clan.
This request requires OAuth2: oauth2: AdminGroups scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - group_id (
int): The group id. - membership_id (
int): The member id to unban. - membership_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The member's membership type.
1270 async def kick_clan_member( 1271 self, 1272 access_token: str, 1273 /, 1274 group_id: int, 1275 membership_id: int, 1276 membership_type: typedefs.IntAnd[enums.MembershipType], 1277 ) -> typedefs.JSONObject: 1278 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1279 resp = await self._request( 1280 RequestMethod.POST, 1281 f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Kick/", 1282 auth=access_token, 1283 ) 1284 assert isinstance(resp, dict) 1285 return resp
Kick a member from the clan.
This request requires OAuth2: oauth2: AdminGroups scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - group_id (
int): The group id. - membership_id (
int): The member id to kick. - membership_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The member's membership type.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the group that the member has been kicked from.
1287 async def edit_clan( 1288 self, 1289 access_token: str, 1290 /, 1291 group_id: int, 1292 *, 1293 name: typedefs.NoneOr[str] = None, 1294 about: typedefs.NoneOr[str] = None, 1295 motto: typedefs.NoneOr[str] = None, 1296 theme: typedefs.NoneOr[str] = None, 1297 tags: typedefs.NoneOr[collections.Sequence[str]] = None, 1298 is_public: typedefs.NoneOr[bool] = None, 1299 locale: typedefs.NoneOr[str] = None, 1300 avatar_image_index: typedefs.NoneOr[int] = None, 1301 membership_option: typedefs.NoneOr[ 1302 typedefs.IntAnd[enums.MembershipOption] 1303 ] = None, 1304 allow_chat: typedefs.NoneOr[bool] = None, 1305 chat_security: typedefs.NoneOr[typing.Literal[0, 1]] = None, 1306 call_sign: typedefs.NoneOr[str] = None, 1307 homepage: typedefs.NoneOr[typing.Literal[0, 1, 2]] = None, 1308 enable_invite_messaging_for_admins: typedefs.NoneOr[bool] = None, 1309 default_publicity: typedefs.NoneOr[typing.Literal[0, 1, 2]] = None, 1310 is_public_topic_admin: typedefs.NoneOr[bool] = None, 1311 ) -> None: 1312 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1313 payload = { 1314 "name": name, 1315 "about": about, 1316 "motto": motto, 1317 "theme": theme, 1318 "tags": tags, 1319 "isPublic": is_public, 1320 "avatarImageIndex": avatar_image_index, 1321 "isPublicTopicAdminOnly": is_public_topic_admin, 1322 "allowChat": allow_chat, 1323 "chatSecurity": chat_security, 1324 "callsign": call_sign, 1325 "homepage": homepage, 1326 "enableInvitationMessagingForAdmins": enable_invite_messaging_for_admins, 1327 "defaultPublicity": default_publicity, 1328 "locale": locale, 1329 } 1330 if membership_option is not None: 1331 payload["membershipOption"] = int(membership_option) 1332 1333 await self._request( 1334 RequestMethod.POST, 1335 f"GroupV2/{group_id}/Edit", 1336 json=payload, 1337 auth=access_token, 1338 )
Edit a clan.
Notes
- This request requires OAuth2: oauth2:
AdminGroupsscope. - All arguments will default to
Noneif not provided. This does not includeaccess_tokenandgroup_id
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - group_id (
int): The group id to edit.
Other Parameters
- name (
aiobungie.typedefs.NoneOr[str]): The name to edit the clan with. - about (
aiobungie.typedefs.NoneOr[str]): The about section to edit the clan with. - motto (
aiobungie.typedefs.NoneOr[str]): The motto section to edit the clan with. - theme (
aiobungie.typedefs.NoneOr[str]): The theme name to edit the clan with. - tags (
aiobungie.typedefs.NoneOr[collections.Sequence[str]]): A sequence of strings to replace the clan tags with. - is_public (
aiobungie.typedefs.NoneOr[bool]): If provided and set toTrue, The clan will set to private. If provided and set toFalse, The clan will set to public whether it was or not. - locale (
aiobungie.typedefs.NoneOr[str]): The locale section to edit the clan with. - avatar_image_index (
aiobungie.typedefs.NoneOr[int]): The clan avatar image index to edit the clan with. - membership_option :
aiobungie.typedefs.NoneOr[aiobungie.typedefs.IntAnd[aiobungie.MembershipOption]]# noqa (E501 # Line too long): The clan membership option to edit it with. - allow_chat (
aiobungie.typedefs.NoneOr[bool]): If provided and set toTrue, The clan members will be allowed to chat. If provided and set toFalse, The clan members will not be allowed to chat. - chat_security (
aiobungie.typedefs.NoneOr[typing.Literal[0, 1]]): If provided and set to0, The clan chat security will be edited toGrouponly. If provided and set to1, The clan chat security will be edited toAdminonly. - call_sign (
aiobungie.typedefs.NoneOr[str]): The clan call sign to edit it with. - homepage (
aiobungie.typedefs.NoneOr[typing.Literal[0, 1, 2]]): If provided and set to0, The clan chat homepage will be edited toWall. If provided and set to1, The clan chat homepage will be edited toForum. If provided and set to0, The clan chat homepage will be edited toAllianceForum. - enable_invite_messaging_for_admins (
aiobungie.typedefs.NoneOr[bool]): ??? - default_publicity (
aiobungie.typedefs.NoneOr[typing.Literal[0, 1, 2]]): If provided and set to0, The clan chat publicity will be edited toPublic. If provided and set to1, The clan chat publicity will be edited toAlliance. If provided and set to2, The clan chat publicity will be edited toPrivate. - is_public_topic_admin (
aiobungie.typedefs.NoneOr[bool]): ???
1340 async def edit_clan_options( 1341 self, 1342 access_token: str, 1343 /, 1344 group_id: int, 1345 *, 1346 invite_permissions_override: typedefs.NoneOr[bool] = None, 1347 update_culture_permissionOverride: typedefs.NoneOr[bool] = None, 1348 host_guided_game_permission_override: typedefs.NoneOr[ 1349 typing.Literal[0, 1, 2] 1350 ] = None, 1351 update_banner_permission_override: typedefs.NoneOr[bool] = None, 1352 join_level: typedefs.NoneOr[typedefs.IntAnd[enums.ClanMemberType]] = None, 1353 ) -> None: 1354 payload = { 1355 "InvitePermissionOverride": invite_permissions_override, 1356 "UpdateCulturePermissionOverride": update_culture_permissionOverride, 1357 "HostGuidedGamePermissionOverride": host_guided_game_permission_override, 1358 "UpdateBannerPermissionOverride": update_banner_permission_override, 1359 "JoinLevel": int(join_level) if join_level else None, 1360 } 1361 1362 await self._request( 1363 RequestMethod.POST, 1364 f"GroupV2/{group_id}/EditFounderOptions", 1365 json=payload, 1366 auth=access_token, 1367 )
Edit the clan options.
Notes
- This request requires OAuth2: oauth2:
AdminGroupsscope. - All arguments will default to
Noneif not provided. This does not includeaccess_tokenandgroup_id
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - group_id (
int): The group id.
Other Parameters
- invite_permissions_override (
aiobungie.typedefs.NoneOr[bool]): Minimum Member Level allowed to invite new members to group Always Allowed: Founder, Acting Founder True means admins have this power, false means they don't Default is False for clans, True for groups. - update_culture_permissionOverride (
aiobungie.typedefs.NoneOr[bool]): Minimum Member Level allowed to update group culture Always Allowed: Founder, Acting Founder True means admins have this power, false means they don't Default is False for clans, True for groups. - host_guided_game_permission_override (
aiobungie.typedefs.NoneOr[typing.Literal[0, 1, 2]]): Minimum Member Level allowed to host guided games Always Allowed: Founder, Acting Founder, Admin Allowed Overrides:0-> None,1-> Beginner2-> Member. Default is Member for clans, None for groups, although this means nothing for groups. - update_banner_permission_override (
aiobungie.typedefs.NoneOr[bool]): Minimum Member Level allowed to update banner Always Allowed: Founder, Acting Founder True means admins have this power, false means they don't Default is False for clans, True for groups. - join_level (
aiobungie.ClanMemberType): Level to join a member at when accepting an invite, application, or joining an open clan. Default isaiobungie.ClanMemberType.BEGINNER
1369 async def fetch_friends(self, access_token: str, /) -> typedefs.JSONObject: 1370 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1371 resp = await self._request( 1372 RequestMethod.GET, 1373 "Social/Friends/", 1374 auth=access_token, 1375 ) 1376 assert isinstance(resp, dict) 1377 return resp
Fetch bungie friend list.
This requests OAuth2: ReadUserData scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account.
Returns
aiobungie.typedefs.JSONObject: A JSON object of an array of the bungie friends's data.
1379 async def fetch_friend_requests(self, access_token: str, /) -> typedefs.JSONObject: 1380 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1381 resp = await self._request( 1382 RequestMethod.GET, 1383 "Social/Friends/Requests", 1384 auth=access_token, 1385 ) 1386 assert isinstance(resp, dict) 1387 return resp
Fetch pending bungie friend requests queue.
This requests OAuth2: ReadUserData scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account.
Returns
aiobungie.typedefs.JSONObject: A JSON object of incoming requests and outgoing requests.
1389 async def accept_friend_request(self, access_token: str, /, member_id: int) -> None: 1390 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1391 await self._request( 1392 RequestMethod.POST, 1393 f"Social/Friends/Requests/Accept/{member_id}", 1394 auth=access_token, 1395 )
Accepts a friend relationship with the target user. The user must be on your incoming friend request list.
This request requires OAuth2: BnetWrite scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - member_id (
int): The member's id to accept.
1397 async def send_friend_request(self, access_token: str, /, member_id: int) -> None: 1398 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1399 await self._request( 1400 RequestMethod.POST, 1401 f"Social/Friends/Add/{member_id}", 1402 auth=access_token, 1403 )
Requests a friend relationship with the target user.
This request requires OAuth2: BnetWrite scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - member_id (
int): The member's id to send the request to.
1405 async def decline_friend_request( 1406 self, access_token: str, /, member_id: int 1407 ) -> None: 1408 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1409 await self._request( 1410 RequestMethod.POST, 1411 f"Social/Friends/Requests/Decline/{member_id}", 1412 auth=access_token, 1413 )
Decline a friend request with the target user. The user must be in your incoming friend request list.
This request requires OAuth2: BnetWrite scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - member_id (
int): The member's id to decline.
1415 async def remove_friend(self, access_token: str, /, member_id: int) -> None: 1416 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1417 await self._request( 1418 RequestMethod.POST, 1419 f"Social/Friends/Remove/{member_id}", 1420 auth=access_token, 1421 )
Removes a friend from your friend list. The user must be in your friend list.
This request requires OAuth2: BnetWrite scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - member_id (
int): The member's id to remove.
1423 async def remove_friend_request(self, access_token: str, /, member_id: int) -> None: 1424 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> 1425 await self._request( 1426 RequestMethod.POST, 1427 f"Social/Friends/Requests/Remove/{member_id}", 1428 auth=access_token, 1429 )
Removes a friend from your friend list requests. The user must be in your outgoing request list.
.. note : This request requires OAuth2: BnetWrite scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - member_id (
int): The member's id to remove from the requested friend list.
1431 async def approve_all_pending_group_users( 1432 self, 1433 access_token: str, 1434 /, 1435 group_id: int, 1436 message: undefined.UndefinedOr[str] = undefined.UNDEFINED, 1437 ) -> None: 1438 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> 1439 await self._request( 1440 RequestMethod.POST, 1441 f"GroupV2/{group_id}/Members/ApproveAll", 1442 auth=access_token, 1443 json={"message": str(message)}, 1444 )
Approve all pending users for the given group id.
This request requires OAuth2: AdminGroups scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - group_id (
int): The given group id.
Other Parameters
- message (
aiobungie.UndefinedOr[str]): An optional message to send with the request. Default isUNDEFINED.
1446 async def deny_all_pending_group_users( 1447 self, 1448 access_token: str, 1449 /, 1450 group_id: int, 1451 *, 1452 message: undefined.UndefinedOr[str] = undefined.UNDEFINED, 1453 ) -> None: 1454 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> 1455 await self._request( 1456 RequestMethod.POST, 1457 f"GroupV2/{group_id}/Members/DenyAll", 1458 auth=access_token, 1459 json={"message": str(message)}, 1460 )
Deny all pending users for the given group id.
This request requires OAuth2: AdminGroups scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - group_id (
int): The given group id.
Other Parameters
- message (
aiobungie.UndefinedOr[str]): An optional message to send with the request. Default isUNDEFINED.
1462 async def add_optional_conversation( 1463 self, 1464 access_token: str, 1465 /, 1466 group_id: int, 1467 *, 1468 name: undefined.UndefinedOr[str] = undefined.UNDEFINED, 1469 security: typing.Literal[0, 1] = 0, 1470 ) -> None: 1471 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> 1472 payload = {"chatName": str(name), "chatSecurity": security} 1473 await self._request( 1474 RequestMethod.POST, 1475 f"GroupV2/{group_id}/OptionalConversations/Add", 1476 json=payload, 1477 auth=access_token, 1478 )
Add a new chat channel to a group.
This request requires OAuth2: AdminGroups scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - group_id (
int): The given group id.
Other parameters
name: aiobungie.UndefinedOr[str]
The chat name. Default to UNDEFINED
security: typing.Literal[0, 1]
The security level of the chat.
If provided and set to 0, It will be to `Group` only.
If provided and set to 1, It will be `Admins` only.
Default is `0`
1480 async def edit_optional_conversation( 1481 self, 1482 access_token: str, 1483 /, 1484 group_id: int, 1485 conversation_id: int, 1486 *, 1487 name: undefined.UndefinedOr[str] = undefined.UNDEFINED, 1488 security: typing.Literal[0, 1] = 0, 1489 enable_chat: bool = False, 1490 ) -> None: 1491 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> 1492 payload = { 1493 "chatEnabled": enable_chat, 1494 "chatName": str(name), 1495 "chatSecurity": security, 1496 } 1497 await self._request( 1498 RequestMethod.POST, 1499 f"GroupV2/{group_id}/OptionalConversations/Edit/{conversation_id}", 1500 json=payload, 1501 auth=access_token, 1502 )
Edit the settings of this chat channel.
This request requires OAuth2: AdminGroups scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - group_id (
int): The given group id. - conversation_id (
int): The conversation/chat id.
Other parameters
name: aiobungie.UndefinedOr[str]
The new chat name. Default to UNDEFINED
security: typing.Literal[0, 1]
The new security level of the chat.
If provided and set to 0, It will be to `Group` only.
If provided and set to 1, It will be `Admins` only.
Default is `0`
enable_chat : bool
Whether to enable chatting or not.
If set to True then chatting will be enabled. Otherwise it will be disabled.
1504 async def transfer_item( 1505 self, 1506 access_token: str, 1507 /, 1508 item_id: int, 1509 item_hash: int, 1510 character_id: int, 1511 member_type: typedefs.IntAnd[enums.MembershipType], 1512 *, 1513 stack_size: int = 1, 1514 vault: bool = False, 1515 ) -> None: 1516 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> 1517 payload = { 1518 "characterId": character_id, 1519 "membershipType": int(member_type), 1520 "itemId": item_id, 1521 "itemReferenceHash": item_hash, 1522 "stackSize": stack_size, 1523 "transferToVault": vault, 1524 } 1525 await self._request( 1526 RequestMethod.POST, 1527 "Destiny2/Actions/Items/TransferItem", 1528 json=payload, 1529 auth=access_token, 1530 )
Transfer an item from / to your vault.
Notes
- This method requires OAuth2: MoveEquipDestinyItems scope.
- This method requires both item id and hash.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - item_id (
int): The item instance id you to transfer. - item_hash (
int): The item hash. - character_id (
int): The character id to transfer the item from/to. - member_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The user membership type.
Other Parameters
- stack_size (
int): The item stack size. - valut (
bool): Whether to transfer this item to your valut or not. Defaults toFalse.
1532 async def pull_item( 1533 self, 1534 access_token: str, 1535 /, 1536 item_id: int, 1537 item_hash: int, 1538 character_id: int, 1539 member_type: typedefs.IntAnd[enums.MembershipType], 1540 *, 1541 stack_size: int = 1, 1542 vault: bool = False, 1543 ) -> None: 1544 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> 1545 payload = { 1546 "characterId": character_id, 1547 "membershipType": int(member_type), 1548 "itemId": item_id, 1549 "itemReferenceHash": item_hash, 1550 "stackSize": stack_size, 1551 "transferToVault": vault, 1552 } 1553 await self._request( 1554 RequestMethod.POST, 1555 "Destiny2/Actions/Items/PullFromPostmaster", 1556 json=payload, 1557 auth=access_token, 1558 )
pull an item from the postmaster.
Notes
- This method requires OAuth2: MoveEquipDestinyItems scope.
- This method requires both item id and hash.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - item_id (
int): The item instance id to pull. - item_hash (
int): The item hash. - character_id (
int): The character id to pull the item to. - member_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The user membership type.
Other Parameters
- stack_size (
int): The item stack size. - valut (
bool): Whether to pill this item to your valut or not. Defaults toFalse.
1560 async def fetch_fireteams( 1561 self, 1562 activity_type: typedefs.IntAnd[fireteams.FireteamActivity], 1563 *, 1564 platform: typedefs.IntAnd[ 1565 fireteams.FireteamPlatform 1566 ] = fireteams.FireteamPlatform.ANY, 1567 language: typing.Union[ 1568 fireteams.FireteamLanguage, str 1569 ] = fireteams.FireteamLanguage.ALL, 1570 date_range: typedefs.IntAnd[ 1571 fireteams.FireteamDate 1572 ] = fireteams.FireteamDate.ALL, 1573 page: int = 0, 1574 slots_filter: int = 0, 1575 ) -> typedefs.JSONObject: 1576 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1577 resp = await self._request( 1578 RequestMethod.GET, 1579 f"Fireteam/Search/Available/{int(platform)}/{int(activity_type)}/{int(date_range)}/{slots_filter}/{page}/?langFilter={str(language)}", # noqa: E501 Line too long 1580 ) 1581 assert isinstance(resp, dict) 1582 return resp
Fetch public Bungie fireteams with open slots.
Parameters
- activity_type (
aiobungie.typedefs.IntAnd[aiobungie.crates.FireteamActivity]): The fireteam activity type.
Other Parameters
- platform (
aiobungie.typedefs.IntAnd[FireteamPlatform]): If this is provided. Then the results will be filtered with the given platform. Defaults toaiobungie.crates.FireteamPlatform.ANYwhich returns all platforms. - language (
typing.Union[FireteamLanguage, str]): A locale language to filter the used language in that fireteam. Defaults toaiobungie.crates.FireteamLanguage.ALL - date_range (
aiobungie.typedefs.IntAnd[aiobungie.FireteamDate]): An integer to filter the date range of the returned fireteams. Defaults toaiobungie.FireteamDate.ALL. - page (
int): The page number. By default its0which returns all available activities. - slots_filter (
int): Filter the returned fireteams based on available slots. Default is0
Returns
aiobungie.typedefs.JSONObject: A JSON object of the fireteam details.
1584 async def fetch_avaliable_clan_fireteams( 1585 self, 1586 access_token: str, 1587 group_id: int, 1588 activity_type: typedefs.IntAnd[fireteams.FireteamActivity], 1589 *, 1590 platform: typedefs.IntAnd[fireteams.FireteamPlatform], 1591 language: typing.Union[fireteams.FireteamLanguage, str], 1592 date_range: typedefs.IntAnd[ 1593 fireteams.FireteamDate 1594 ] = fireteams.FireteamDate.ALL, 1595 page: int = 0, 1596 public_only: bool = False, 1597 slots_filter: int = 0, 1598 ) -> typedefs.JSONObject: 1599 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1600 resp = await self._request( 1601 RequestMethod.GET, 1602 f"Fireteam/Clan/{group_id}/Available/{int(platform)}/{int(activity_type)}/{int(date_range)}/{slots_filter}/{public_only}/{page}", # noqa: E501 1603 json={"langFilter": str(language)}, 1604 auth=access_token, 1605 ) 1606 assert isinstance(resp, dict) 1607 return resp
Fetch a clan's fireteams with open slots.
This method requires OAuth2: ReadGroups scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - group_id (
int): The group/clan id of the fireteam. - activity_type (
aiobungie.typedefs.IntAnd[aiobungie.crates.FireteamActivity]): The fireteam activity type.
Other Parameters
- platform (
aiobungie.typedefs.IntAnd[FireteamPlatform]): If this is provided. Then the results will be filtered with the given platform. Defaults toaiobungie.crates.FireteamPlatform.ANYwhich returns all platforms. - language (
typing.Union[FireteamLanguage, str]): A locale language to filter the used language in that fireteam. Defaults toaiobungie.crates.FireteamLanguage.ALL - date_range (
aiobungie.typedefs.IntAnd[aiobungie.FireteamDate]): An integer to filter the date range of the returned fireteams. Defaults toaiobungie.FireteamDate.ALL. - page (
int): The page number. By default its0which returns all available activities. - public_only (
bool): If set to True, Then only public fireteams will be returned. - slots_filter (
int): Filter the returned fireteams based on available slots. Default is0
Returns
aiobungie.typedefs.JSONObject: A JSON object of the fireteams detail.
1609 async def fetch_clan_fireteam( 1610 self, access_token: str, fireteam_id: int, group_id: int 1611 ) -> typedefs.JSONObject: 1612 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1613 resp = await self._request( 1614 RequestMethod.GET, 1615 f"Fireteam/Clan/{group_id}/Summary/{fireteam_id}", 1616 auth=access_token, 1617 ) 1618 assert isinstance(resp, dict) 1619 return resp
Fetch a specific clan fireteam.
This method requires OAuth2: ReadGroups scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - group_id (
int): The group/clan id to fetch the fireteam from. - fireteam_id (
int): The fireteam id to fetch.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the fireteam details.
1621 async def fetch_my_clan_fireteams( 1622 self, 1623 access_token: str, 1624 group_id: int, 1625 *, 1626 include_closed: bool = True, 1627 platform: typedefs.IntAnd[fireteams.FireteamPlatform], 1628 language: typing.Union[fireteams.FireteamLanguage, str], 1629 filtered: bool = True, 1630 page: int = 0, 1631 ) -> typedefs.JSONObject: 1632 payload = {"groupFilter": filtered, "langFilter": str(language)} 1633 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1634 resp = await self._request( 1635 RequestMethod.GET, 1636 f"Fireteam/Clan/{group_id}/My/{int(platform)}/{include_closed}/{page}", 1637 json=payload, 1638 auth=access_token, 1639 ) 1640 assert isinstance(resp, dict) 1641 return resp
Fetch a clan's fireteams with open slots.
This method requires OAuth2: ReadGroups scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - group_id (
int): The group/clan id to fetch.
Other Parameters
- include_closed (
bool): If provided and set toTrue, It will also return closed fireteams. If provided and set toFalse, It will only return public fireteams. Default isTrue. - platform (
aiobungie.typedefs.IntAnd[FireteamPlatform]): If this is provided. Then the results will be filtered with the given platform. Defaults toaiobungie.crates.FireteamPlatform.ANYwhich returns all platforms. - language (
typing.Union[FireteamLanguage, str]): A locale language to filter the used language in that fireteam. Defaults toaiobungie.crates.FireteamLanguage.ALL - filtered (
bool): If set toTrue, it will filter by clan. Otherwise not. Default isTrue. - page (
int): The page number. By default its0which returns all available activities.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the fireteams detail.
1643 async def fetch_private_clan_fireteams( 1644 self, access_token: str, group_id: int, / 1645 ) -> int: 1646 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1647 resp = await self._request( 1648 RequestMethod.GET, 1649 f"Fireteam/Clan/{group_id}/ActiveCount", 1650 auth=access_token, 1651 ) 1652 assert isinstance(resp, int) 1653 return resp
Fetch the active count of the clan fireteams that are only private.
This method requires OAuth2: ReadGroups scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - group_id (
int): The group/clan id.
Returns
int: The active fireteams count. Max value returned is 25.
1655 async def fetch_post_activity(self, instance_id: int, /) -> typedefs.JSONObject: 1656 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1657 resp = await self._request( 1658 RequestMethod.GET, f"Destiny2/Stats/PostGameCarnageReport/{instance_id}" 1659 ) 1660 assert isinstance(resp, dict) 1661 return resp
Fetch a post activity details.
Parameters
- instance_id (
int): The activity instance id.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the post activity.
1663 async def search_entities( 1664 self, name: str, entity_type: str, *, page: int = 0 1665 ) -> typedefs.JSONObject: 1666 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1667 resp = await self._request( 1668 RequestMethod.GET, 1669 f"Destiny2/Armory/Search/{entity_type}/{name}/", 1670 json={"page": page}, 1671 ) 1672 assert isinstance(resp, dict) 1673 return resp
Search for Destiny2 entities given a name and its type.
Parameters
- name (
str): The name of the entity, i.e., Thunderlord, One thousand voices. - entity_type (
str): The type of the entity, AKA Definition, For an exampleDestinyInventoryItemDefinition
Other Parameters
- page (
int): An optional page to return. Default to 0.
Returns
aiobungie.typedefs.JSONObject: A JSON object contains details about the searched term.
1675 async def fetch_unique_weapon_history( 1676 self, 1677 membership_id: int, 1678 character_id: int, 1679 membership_type: typedefs.IntAnd[enums.MembershipType], 1680 ) -> typedefs.JSONObject: 1681 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1682 resp = await self._request( 1683 RequestMethod.GET, 1684 f"Destiny2/{int(membership_type)}/Account/{membership_id}/Character/{character_id}/Stats/UniqueWeapons/", 1685 ) 1686 assert isinstance(resp, dict) 1687 return resp
Fetch details about unique weapon usage for a character. Includes all exotics.
Parameters
- membership_id (
int): The Destiny user membership id. - character_id (
int): The character id to retrieve. - membership_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The Destiny user's membership type.
Returns
aiobungie.typedefs.JSONObject: A JSON object contains details about the returned weapons.
1689 async def fetch_item( 1690 self, 1691 member_id: int, 1692 item_id: int, 1693 membership_type: typedefs.IntAnd[enums.MembershipType], 1694 components: list[enums.ComponentType], 1695 ) -> typedefs.JSONObject: 1696 collector = _collect_components(components) 1697 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1698 resp = await self._request( 1699 RequestMethod.GET, 1700 f"Destiny2/{int(membership_type)}/Profile/{member_id}/Item/{item_id}/?components={collector}", 1701 ) 1702 assert isinstance(resp, dict) 1703 return resp
Fetch an instanced Destiny 2 item's details.
Parameters
- member_id (
int): The membership id of the Destiny 2 player. - item_id (
int): The instance id of the item. - membership_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The membership type of the Destiny 2 player. - components (
list[aiobungie.ComponentType]): A list of components to retrieve.
Returns
aiobungie.typedefs.JSONObject: A JSON object response contains the fetched item with its components.
1705 async def fetch_clan_weekly_rewards(self, clan_id: int, /) -> typedefs.JSONObject: 1706 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1707 resp = await self._request( 1708 RequestMethod.GET, f"Destiny2/Clan/{clan_id}/WeeklyRewardState/" 1709 ) 1710 assert isinstance(resp, dict) 1711 return resp
Fetch the weekly reward state for a clan.
Parameters
- clan_id (
int): The clan id.
Returns
aiobungie.typedefs.JSONObject: A JSON response of the clan rewards state.
1713 async def fetch_available_locales(self) -> typedefs.JSONObject: 1714 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1715 resp = await self._request( 1716 RequestMethod.GET, "Destiny2/Manifest/DestinyLocaleDefinition/" 1717 ) 1718 assert isinstance(resp, dict) 1719 return resp
Fetch available locales at Bungie.
Returns
aiobungie.typedefs.JSONObject: A JSON object contains a list of all available localization cultures.
1721 async def fetch_common_settings(self) -> typedefs.JSONObject: 1722 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1723 resp = await self._request(RequestMethod.GET, "Settings") 1724 assert isinstance(resp, dict) 1725 return resp
Fetch the common settings used by Bungie's envirotment.
Returns
aiobungie.typedefs.JSONObject: The common settings JSON object.
1727 async def fetch_user_systems_overrides(self) -> typedefs.JSONObject: 1728 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1729 resp = await self._request(RequestMethod.GET, "UserSystemOverrides") 1730 assert isinstance(resp, dict) 1731 return resp
Fetch a user's specific system overrides.
Returns
aiobungie.typedefs.JSONObject: The system overrides JSON object.
1733 async def fetch_global_alerts( 1734 self, *, include_streaming: bool = False 1735 ) -> typedefs.JSONArray: 1736 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1737 resp = await self._request( 1738 RequestMethod.GET, f"GlobalAlerts/?includestreaming={include_streaming}" 1739 ) 1740 assert isinstance(resp, list) 1741 return resp
Fetch any active global alerts.
Parameters
- include_streaming (
bool): If True, the returned results will include streaming alerts. Default is False.
Returns
aiobungie.typedefs.JSONArray: A JSON array of the global alerts objects.
1743 async def awainitialize_request( 1744 self, 1745 access_token: str, 1746 type: typing.Literal[0, 1], 1747 membership_type: typedefs.IntAnd[enums.MembershipType], 1748 /, 1749 *, 1750 affected_item_id: typing.Optional[int] = None, 1751 character_id: typing.Optional[int] = None, 1752 ) -> typedefs.JSONObject: 1753 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1754 1755 body = {"type": type, "membershipType": int(membership_type)} 1756 1757 if affected_item_id is not None: 1758 body["affectedItemId"] = affected_item_id 1759 1760 if character_id is not None: 1761 body["characterId"] = character_id 1762 1763 resp = await self._request( 1764 RequestMethod.POST, "Destiny2/Awa/Initialize", json=body, auth=access_token 1765 ) 1766 assert isinstance(resp, dict) 1767 return resp
Initialize a request to perform an advanced write action.
OAuth2: AdvancedWriteActions application scope is required to perform this request.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - type (
typing.Literal[0, 1]): Type of the advanced write action. Its either 0 or 1. If set to 0 that means itNone. Otherwise if 1 that means its insert plugs. - membership_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The Destiny membership type of the account to modify.
Other Parameters
- affected_item_id (
typing.Optional[int]): Item instance ID the action shall be applied to. This is optional for all but a new AwaType values. - character_id (
typing.Optional[int]): The Destiny character ID to perform this action on.
Returns
aiobungie.typedefs.JSONObject: A JSON object response.
1769 async def awaget_action_token( 1770 self, access_token: str, correlation_id: str, / 1771 ) -> typedefs.JSONObject: 1772 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1773 resp = await self._request( 1774 RequestMethod.POST, 1775 f"Destiny2/Awa/GetActionToken/{correlation_id}", 1776 auth=access_token, 1777 ) 1778 assert isinstance(resp, dict) 1779 return resp
Returns the action token if user approves the request.
OAuth2: AdvancedWriteActions application scope is required to perform this request.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - correlation_id (
str): The identifier for the advanced write action request.
Returns
aiobungie.typedefs.JSONObject: A JSON object response.
1801 async def fetch_vendors( 1802 self, 1803 access_token: str, 1804 character_id: int, 1805 membership_id: int, 1806 membership_type: typedefs.IntAnd[enums.MembershipType], 1807 /, 1808 components: list[enums.ComponentType], 1809 filter: typing.Optional[int] = None, 1810 ) -> typedefs.JSONObject: 1811 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1812 components_ = _collect_components(components) 1813 route = ( 1814 f"Destiny2/{int(membership_type)}/Profile/{membership_id}" 1815 f"/Character/{character_id}/Vendors/?components={components_}" 1816 ) 1817 1818 if filter is not None: 1819 route = route + f"&filter={filter}" 1820 1821 resp = await self._request( 1822 RequestMethod.GET, 1823 route, 1824 auth=access_token, 1825 ) 1826 assert isinstance(resp, dict) 1827 return resp
Get currently available vendors from the list of vendors that can possibly have rotating inventory.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - character_id (
int): The character ID to return the vendor info for. - membership_id (
int): The Destiny membership id to return the vendor info for. - membership_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The Destiny membership type to return the vendor info for. - components (
list[aiobungie.ComponentType]): A list of vendor components to collect and return.
Other Parameters
- filter (
int): Filters the type of items returned from the vendor. This can be left toNone.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the vendor response.
1829 async def fetch_vendor( 1830 self, 1831 access_token: str, 1832 character_id: int, 1833 membership_id: int, 1834 membership_type: typedefs.IntAnd[enums.MembershipType], 1835 vendor_hash: int, 1836 /, 1837 components: list[enums.ComponentType], 1838 ) -> typedefs.JSONObject: 1839 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1840 components_ = _collect_components(components) 1841 resp = await self._request( 1842 RequestMethod.GET, 1843 ( 1844 f"Destiny2/{int(membership_type)}/Profile/{membership_id}" 1845 f"/Character/{character_id}/Vendors/{vendor_hash}/?components={components_}" 1846 ), 1847 auth=access_token, 1848 ) 1849 assert isinstance(resp, dict) 1850 return resp
Fetch details for a specific vendor.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - character_id (
int): The character ID to return the vendor info for. - membership_id (
int): The Destiny membership id to return the vendor info for. - membership_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The Destiny membership type to return the vendor info for. - vendor_hash (
int): The vendor hash to return the details for. - components (
list[aiobungie.ComponentType]): A list of vendor components to collect and return.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the vendor response.
1852 async def fetch_application_api_usage( 1853 self, 1854 access_token: str, 1855 application_id: int, 1856 /, 1857 *, 1858 start: typing.Optional[datetime.datetime] = None, 1859 end: typing.Optional[datetime.datetime] = None, 1860 ) -> typedefs.JSONObject: 1861 end_date, start_date = time.parse_date_range(end, start) 1862 resp = await self._request( 1863 RequestMethod.GET, 1864 f"App/ApiUsage/{application_id}/?end={end_date}&start={start_date}", 1865 auth=access_token, 1866 ) 1867 assert isinstance(resp, dict) 1868 return resp
Fetch a Bungie application's API usage.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - application_id (
int): The application id to get.
Other Parameters
start (
typing.Optional[datetime.datetime]): A datetime object can be used to collect the start of the application usage. This is limited and can go back to 30 days maximum.If this is left to
None. It will return the last 24 hours.end (
typing.Optional[datetime.datetime]): A datetime object can be used to collect the end of the application usage.If this is left to
None. It will returnnow.
Example
import datetime
# Fetch data from 2021 Dec 10th to 2021 Dec 20th
await fetch_application_api_usage(
start=datetime.datetime(2021, 12, 10), end=datetime.datetime(2021, 12, 20)
)
Returns
aiobungie.typedefs.JSONObject: A JSON object of the application usage details.
1870 async def fetch_bungie_applications(self) -> typedefs.JSONArray: 1871 resp = await self._request(RequestMethod.GET, "App/FirstParty") 1872 assert isinstance(resp, list) 1873 return resp
Fetch details for applications created by Bungie.
Returns
aiobungie.typedefs.JSONArray: An array of Bungie created applications.
1880 async def fetch_content_by_id( 1881 self, id: int, locale: str, /, *, head: bool = False 1882 ) -> typedefs.JSONObject: 1883 resp = await self._request( 1884 RequestMethod.GET, 1885 f"Content/GetContentById/{id}/{locale}/", 1886 json={"head": head}, 1887 ) 1888 assert isinstance(resp, dict) 1889 return resp
1891 async def fetch_content_by_tag_and_type( 1892 self, locale: str, tag: str, type: str, *, head: bool = False 1893 ) -> typedefs.JSONObject: 1894 resp = await self._request( 1895 RequestMethod.GET, 1896 f"Content/GetContentByTagAndType/{tag}/{type}/{locale}/", 1897 json={"head": head}, 1898 ) 1899 assert isinstance(resp, dict) 1900 return resp
1902 async def search_content_with_text( 1903 self, 1904 locale: str, 1905 /, 1906 content_type: str, 1907 search_text: str, 1908 tag: str, 1909 *, 1910 page: undefined.UndefinedOr[int] = undefined.UNDEFINED, 1911 source: undefined.UndefinedOr[str] = undefined.UNDEFINED, 1912 ) -> typedefs.JSONObject: 1913 body: typedefs.JSONObject = {} 1914 1915 body["ctype"] = content_type 1916 body["searchtext"] = search_text 1917 body["tag"] = tag 1918 1919 if page is not undefined.UNDEFINED: 1920 body["currentpage"] = page 1921 else: 1922 body["currentpage"] = 1 1923 1924 if source is not undefined.UNDEFINED: 1925 body["source"] = source 1926 else: 1927 source = "" 1928 resp = await self._request( 1929 RequestMethod.GET, f"Content/Search/{locale}/", json=body 1930 ) 1931 assert isinstance(resp, dict) 1932 return resp
1934 async def search_content_by_tag_and_type( 1935 self, 1936 locale: str, 1937 tag: str, 1938 type: str, 1939 *, 1940 page: undefined.UndefinedOr[int] = undefined.UNDEFINED, 1941 ) -> typedefs.JSONObject: 1942 body: typedefs.JSONObject = {} 1943 body["currentpage"] = 1 if page is undefined.UNDEFINED else page 1944 resp = await self._request( 1945 RequestMethod.GET, 1946 f"Content/SearchContentByTagAndType/{tag}/{type}/{locale}/", 1947 json=body, 1948 ) 1949 assert isinstance(resp, dict) 1950 return resp
1961 async def fetch_topics_page( 1962 self, 1963 category_filter: int, 1964 group: int, 1965 date_filter: int, 1966 sort: typing.Union[str, bytes], 1967 *, 1968 page: undefined.UndefinedOr[int] = undefined.UNDEFINED, 1969 locales: undefined.UndefinedOr[collections.Iterable[str]] = undefined.UNDEFINED, 1970 tag_filter: undefined.UndefinedOr[str] = undefined.UNDEFINED, 1971 ) -> typedefs.JSONObject: 1972 body: typedefs.JSONObject = {} 1973 if locales is not undefined.UNDEFINED: 1974 body["locales"] = ",".join(str(locales)) 1975 else: 1976 body["locales"] = ",".join([]) 1977 1978 if tag_filter is not undefined.UNDEFINED: 1979 body["tagstring"] = tag_filter 1980 else: 1981 body["tagstring"] = "" 1982 1983 page = 0 if page is not undefined.UNDEFINED else page 1984 1985 resp = await self._request( 1986 RequestMethod.GET, 1987 f"Forum/GetTopicsPaged/{page}/{0}/{group}/{sort!s}/{date_filter}/{category_filter}/", 1988 json=body, 1989 ) 1990 assert isinstance(resp, dict) 1991 return resp
1993 async def fetch_core_topics_page( 1994 self, 1995 category_filter: int, 1996 date_filter: int, 1997 sort: typing.Union[str, bytes], 1998 *, 1999 page: undefined.UndefinedOr[int] = undefined.UNDEFINED, 2000 locales: undefined.UndefinedOr[collections.Iterable[str]] = undefined.UNDEFINED, 2001 ) -> typedefs.JSONObject: 2002 body: typedefs.JSONObject = {} 2003 2004 if locales is not undefined.UNDEFINED: 2005 body["locales"] = ",".join(str(locales)) 2006 else: 2007 body["locales"] = ",".join([]) 2008 2009 resp = await self._request( 2010 RequestMethod.GET, 2011 f"Forum/GetCoreTopicsPaged/{0 if page is undefined.UNDEFINED else page}" 2012 f"/{sort!s}/{date_filter}/{category_filter}/", 2013 json=body, 2014 ) 2015 assert isinstance(resp, dict) 2016 return resp
2018 async def fetch_posts_threaded_page( 2019 self, 2020 parent_post: bool, 2021 page: int, 2022 page_size: int, 2023 parent_post_id: int, 2024 reply_size: int, 2025 root_thread_mode: bool, 2026 sort_mode: int, 2027 show_banned: typing.Optional[str] = None, 2028 ) -> typedefs.JSONObject: 2029 resp = await self._request( 2030 RequestMethod.GET, 2031 f"Forum/GetPostsThreadedPaged/{parent_post}/{page}/" 2032 f"{page_size}/{reply_size}/{parent_post_id}/{root_thread_mode}/{sort_mode}/", 2033 json={"showbanned": show_banned}, 2034 ) 2035 assert isinstance(resp, dict) 2036 return resp
2038 async def fetch_posts_threaded_page_from_child( 2039 self, 2040 child_id: bool, 2041 page: int, 2042 page_size: int, 2043 reply_size: int, 2044 root_thread_mode: bool, 2045 sort_mode: int, 2046 show_banned: typing.Optional[str] = None, 2047 ) -> typedefs.JSONObject: 2048 resp = await self._request( 2049 RequestMethod.GET, 2050 f"Forum/GetPostsThreadedPagedFromChild/{child_id}/" 2051 f"{page}/{page_size}/{reply_size}/{root_thread_mode}/{sort_mode}/", 2052 json={"showbanned": show_banned}, 2053 ) 2054 assert isinstance(resp, dict) 2055 return resp
2057 async def fetch_post_and_parent( 2058 self, child_id: int, /, *, show_banned: typing.Optional[str] = None 2059 ) -> typedefs.JSONObject: 2060 resp = await self._request( 2061 RequestMethod.GET, 2062 f"Forum/GetPostAndParent/{child_id}/", 2063 json={"showbanned": show_banned}, 2064 ) 2065 assert isinstance(resp, dict) 2066 return resp
2068 async def fetch_posts_and_parent_awaiting( 2069 self, child_id: int, /, *, show_banned: typing.Optional[str] = None 2070 ) -> typedefs.JSONObject: 2071 resp = await self._request( 2072 RequestMethod.GET, 2073 f"Forum/GetPostAndParentAwaitingApproval/{child_id}/", 2074 json={"showbanned": show_banned}, 2075 ) 2076 assert isinstance(resp, dict) 2077 return resp
2107 async def fetch_recommended_groups( 2108 self, 2109 accecss_token: str, 2110 /, 2111 *, 2112 date_range: int = 0, 2113 group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN, 2114 ) -> typedefs.JSONArray: 2115 resp = await self._request( 2116 RequestMethod.POST, 2117 f"GroupV2/Recommended/{int(group_type)}/{date_range}/", 2118 auth=accecss_token, 2119 ) 2120 assert isinstance(resp, list) 2121 return resp
2128 async def fetch_user_clan_invite_setting( 2129 self, 2130 access_token: str, 2131 /, 2132 membership_type: typedefs.IntAnd[enums.MembershipType], 2133 ) -> bool: 2134 resp = await self._request( 2135 RequestMethod.GET, 2136 f"GroupV2/GetUserClanInviteSetting/{int(membership_type)}/", 2137 auth=access_token, 2138 ) 2139 assert isinstance(resp, bool) 2140 return resp
2142 async def fetch_banned_group_members( 2143 self, access_token: str, group_id: int, /, *, page: int = 1 2144 ) -> typedefs.JSONObject: 2145 resp = await self._request( 2146 RequestMethod.GET, 2147 f"GroupV2/{group_id}/Banned/?currentpage={page}", 2148 auth=access_token, 2149 ) 2150 assert isinstance(resp, dict) 2151 return resp
2153 async def fetch_pending_group_memberships( 2154 self, access_token: str, group_id: int, /, *, current_page: int = 1 2155 ) -> typedefs.JSONObject: 2156 resp = await self._request( 2157 RequestMethod.GET, 2158 f"GroupV2/{group_id}/Members/Pending/?currentpage={current_page}", 2159 auth=access_token, 2160 ) 2161 assert isinstance(resp, dict) 2162 return resp
2164 async def fetch_invited_group_memberships( 2165 self, access_token: str, group_id: int, /, *, current_page: int = 1 2166 ) -> typedefs.JSONObject: 2167 resp = await self._request( 2168 RequestMethod.GET, 2169 f"GroupV2/{group_id}/Members/InvitedIndividuals/?currentpage={current_page}", 2170 auth=access_token, 2171 ) 2172 assert isinstance(resp, dict) 2173 return resp
2175 async def invite_member_to_group( 2176 self, 2177 access_token: str, 2178 /, 2179 group_id: int, 2180 membership_id: int, 2181 membership_type: typedefs.IntAnd[enums.MembershipType], 2182 *, 2183 message: undefined.UndefinedOr[str] = undefined.UNDEFINED, 2184 ) -> typedefs.JSONObject: 2185 resp = await self._request( 2186 RequestMethod.POST, 2187 f"GroupV2/{group_id}/Members/IndividualInvite/{int(membership_type)}/{membership_id}/", 2188 auth=access_token, 2189 json={"message": str(message)}, 2190 ) 2191 assert isinstance(resp, dict) 2192 return resp
2194 async def cancel_group_member_invite( 2195 self, 2196 access_token: str, 2197 /, 2198 group_id: int, 2199 membership_id: int, 2200 membership_type: typedefs.IntAnd[enums.MembershipType], 2201 ) -> typedefs.JSONObject: 2202 resp = await self._request( 2203 RequestMethod.POST, 2204 f"GroupV2/{group_id}/Members/IndividualInviteCancel/{int(membership_type)}/{membership_id}/", 2205 auth=access_token, 2206 ) 2207 assert isinstance(resp, dict) 2208 return resp
2215 async def fetch_historical_stats( 2216 self, 2217 character_id: int, 2218 membership_id: int, 2219 membership_type: typedefs.IntAnd[enums.MembershipType], 2220 day_start: datetime.datetime, 2221 day_end: datetime.datetime, 2222 groups: list[typedefs.IntAnd[enums.StatsGroupType]], 2223 modes: collections.Sequence[typedefs.IntAnd[enums.GameMode]], 2224 *, 2225 period_type: enums.PeriodType = enums.PeriodType.ALL_TIME, 2226 ) -> typedefs.JSONObject: 2227 end, start = time.parse_date_range(day_end, day_start) 2228 resp = await self._request( 2229 RequestMethod.GET, 2230 f"Destiny2/{int(membership_type)}/Account/{membership_id}/Character/{character_id}/Stats/", 2231 json={ 2232 "dayend": end, 2233 "daystart": start, 2234 "groups": [str(int(group)) for group in groups], 2235 "modes": [str(int(mode)) for mode in modes], 2236 "periodType": int(period_type), 2237 }, 2238 ) 2239 assert isinstance(resp, dict) 2240 return resp
Fetch historical stats for a specific membership character.
Parameters
- character_id (
int): The character ID to return the stats for. - membership_id (
int): The Destiny membership id to return the stats for. - membership_type (
aiobungie.MembershipType | int): The Destiny membership type to return the stats for. - day_start (
datetime.datetime): The start of the day to return the stats for. - day_end (
datetime.datetime): The end of the day to return the stats for. - groups (
list[aiobungie.StatsGroupType]): A list of stats groups to return. - modes (
list[aiobungie.GameMode | int]): A list of game modes to return. - period_type (
aiobungie.enums.PeriodType): The period type to return the stats for. This will returnALL_TIMEby default if not modified.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the historical stats.
2242 async def fetch_historical_stats_for_account( 2243 self, 2244 membership_id: int, 2245 membership_type: typedefs.IntAnd[enums.MembershipType], 2246 groups: list[typedefs.IntAnd[enums.StatsGroupType]], 2247 ) -> typedefs.JSONObject: 2248 resp = await self._request( 2249 RequestMethod.GET, 2250 f"Destiny2/{int(membership_type)}/Account/{membership_id}/Stats/", 2251 json={"groups": [str(int(group)) for group in groups]}, 2252 ) 2253 assert isinstance(resp, dict) 2254 return resp
Fetch historical stats for an account's membership.
Parameters
- membership_id (
int): The Destiny membership id to return the stats for. - membership_type (
aiobungie.MembershipType | int): The Destiny membership type to return the stats for. - groups (
list[aiobungie.StatsGroupType]): A list of stats groups to return.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the historical stats for the account. This includes both the character and account stats.
2256 async def fetch_aggregated_activity_stats( 2257 self, 2258 character_id: int, 2259 membership_id: int, 2260 membership_type: typedefs.IntAnd[enums.MembershipType], 2261 /, 2262 ) -> typedefs.JSONObject: 2263 resp = await self._request( 2264 RequestMethod.GET, 2265 f"Destiny2/{int(membership_type)}/Account/{membership_id}/" 2266 f"Character/{character_id}/Stats/AggregateActivityStats/", 2267 ) 2268 assert isinstance(resp, dict) 2269 return resp
Fetch aggregated activity stats for a specific membership character.
Parameters
- character_id (
int): The character ID to return the stats for. - membership_id (
int): The Destiny membership id to return the stats for. - membership_type (
aiobungie.MembershipType | int): The Destiny membership type to return the stats for.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the aggregated activity stats.
2271 async def equip_loadout( 2272 self, 2273 access_token: str, 2274 /, 2275 loadout_index: int, 2276 character_id: int, 2277 membership_type: typedefs.IntAnd[enums.MembershipType], 2278 ) -> None: 2279 response = await self._request( 2280 RequestMethod.POST, 2281 "Destiny2/Actions/Loadouts/EquipLoadout/", 2282 json={ 2283 "loadoutIndex": loadout_index, 2284 "characterId": character_id, 2285 "membership_type": int(membership_type), 2286 }, 2287 auth=access_token, 2288 ) 2289 assert isinstance(response, int)
Equip a loadout. Youe character must be in a Social space, Orbit or Offline while performing this operation.
This operation requires MoveEquipDestinyItems OAuth2 scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - loadout_index (
int): The index of the loadout to use. - character_id (
int): The character ID to equip the loadout to. - membership_type (
aiobungie.MembershipType | int): The membership type of the account.
2291 async def snapshot_loadout( 2292 self, 2293 access_token: str, 2294 /, 2295 loadout_index: int, 2296 character_id: int, 2297 membership_type: typedefs.IntAnd[enums.MembershipType], 2298 *, 2299 color_hash: typing.Optional[int] = None, 2300 icon_hash: typing.Optional[int] = None, 2301 name_hash: typing.Optional[int] = None, 2302 ) -> None: 2303 response = await self._request( 2304 RequestMethod.POST, 2305 "Destiny2/Actions/Loadouts/SnapshotLoadout/", 2306 auth=access_token, 2307 json={ 2308 "colorHash": color_hash, 2309 "iconHash": icon_hash, 2310 "nameHash": name_hash, 2311 "loadoutIndex": loadout_index, 2312 "characterId": character_id, 2313 "membershipType": int(membership_type), 2314 }, 2315 ) 2316 assert isinstance(response, int)
Snapshot a loadout with the currently equipped items.
This operation requires MoveEquipDestinyItems OAuth2 scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - loadout_index (
int): The index of the loadout to use. - character_id (
int): The character ID to equip the loadout to. - membership_type (
aiobungie.MembershipType | int): The membership type of the account.
Other Parameters
- color_hash (
int | None): ... - icon_hash (
int | None): ... - name_hash (
int | None): ...
2318 async def update_loadout( 2319 self, 2320 access_token: str, 2321 /, 2322 loadout_index: int, 2323 character_id: int, 2324 membership_type: typedefs.IntAnd[enums.MembershipType], 2325 *, 2326 color_hash: typing.Optional[int] = None, 2327 icon_hash: typing.Optional[int] = None, 2328 name_hash: typing.Optional[int] = None, 2329 ) -> None: 2330 response = await self._request( 2331 RequestMethod.POST, 2332 "Destiny2/Actions/Loadouts/UpdateLoadoutIdentifiers/", 2333 auth=access_token, 2334 json={ 2335 "colorHash": color_hash, 2336 "iconHash": icon_hash, 2337 "nameHash": name_hash, 2338 "loadoutIndex": loadout_index, 2339 "characterId": character_id, 2340 "membershipType": int(membership_type), 2341 }, 2342 ) 2343 assert isinstance(response, int)
Update the loadout. Color, Icon and Name.
This operation requires MoveEquipDestinyItems OAuth2 scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - loadout_index (
int): The index of the loadout to use. - character_id (
int): The character ID to equip the loadout to. - membership_type (
aiobungie.MembershipType | int): The membership type of the account.
Other Parameters
- color_hash (
int | None): The new color hash of the loadout to update. - icon_hash (
int | None): The new icon hash of the loadout to update. - name_hash (
int | None): The new name hash of the loadout to update.
2345 async def clear_loadout( 2346 self, 2347 access_token: str, 2348 /, 2349 loadout_index: int, 2350 character_id: int, 2351 membership_type: typedefs.IntAnd[enums.MembershipType], 2352 ) -> None: 2353 response = await self._request( 2354 RequestMethod.POST, 2355 "Destiny2/Actions/Loadouts/ClearLoadout/", 2356 json={ 2357 "loadoutIndex": loadout_index, 2358 "characterId": character_id, 2359 "membership_type": int(membership_type), 2360 }, 2361 auth=access_token, 2362 ) 2363 assert isinstance(response, int)
Clear the identifiers and items of a loadout.
This operation requires MoveEquipDestinyItems OAuth2 scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - loadout_index (
int): The index of the loadout to use. - character_id (
int): The character ID to equip the loadout to. - membership_type (
aiobungie.MembershipType | int): The membership type of the account.
196class RESTPool: 197 """Pool of `RESTClient` instances. 198 199 This allows to create multiple instances of `RESTClient`s that can be acquired 200 which share the same config and metadata. 201 202 Example 203 ------- 204 ```py 205 import aiobungie 206 import asyncio 207 208 client_pool = aiobungie.RESTPool("token", client_id=1234, client_secret='secret') 209 210 # Using a context manager to acquire an instance 211 # of the pool and close the connection after finishing. 212 213 async def first() -> str: 214 async with client_pool.acquire() as client: 215 return client.build_oauth2_url() 216 217 async def second() -> None: 218 async with client_pool.acquire() as client: 219 new_tokens = await client.refresh_access_token("token") 220 client.metadata['tokens'] = new_tokens 221 222 # Client instances are independent from first and second. 223 await asyncio.gather(first(), second()) 224 ``` 225 226 Parameters 227 ---------- 228 token : `str` 229 A valid application token from Bungie's developer portal. 230 231 Other Parameters 232 ---------------- 233 max_retries : `int` 234 The max retries number to retry if the request hit a `5xx` status code. 235 client_secret : `typing.Optional[str]` 236 An optional application client secret, 237 This is only needed if you're fetching OAuth2 tokens with this client. 238 client_id : `typing.Optional[int]` 239 An optional application client id, 240 This is only needed if you're fetching OAuth2 tokens with this client. 241 enable_debugging : `bool | str` 242 Whether to enable logging responses or not. 243 244 Logging Levels 245 -------------- 246 * `False`: This will disable logging. 247 * `True`: This will set the level to `DEBUG` and enable logging minimal information. 248 Like the response status, route, taken time and so on. 249 * `"TRACE" | aiobungie.TRACE`: This will log the response headers along with the minimal information. 250 """ 251 252 __slots__ = ( 253 "_token", 254 "_max_retries", 255 "_client_secret", 256 "_client_id", 257 "_metadata", 258 "_enable_debug", 259 "_client_session", 260 ) 261 262 # Looks like mypy doesn't like this. 263 if typing.TYPE_CHECKING: 264 _enable_debug: typing.Union[typing.Literal["TRACE"], bool, int] 265 266 def __init__( 267 self, 268 token: str, 269 /, 270 *, 271 client_secret: typing.Optional[str] = None, 272 client_id: typing.Optional[int] = None, 273 client_session: typing.Optional[aiohttp.ClientSession] = None, 274 max_retries: int = 4, 275 enable_debugging: typing.Union[typing.Literal["TRACE"], bool, int] = False, 276 ) -> None: 277 self._client_secret = client_secret 278 self._client_id = client_id 279 self._token: str = token 280 self._max_retries = max_retries 281 self._metadata: collections.MutableMapping[typing.Any, typing.Any] = {} 282 self._enable_debug = enable_debugging 283 self._client_session = client_session 284 285 @property 286 def client_id(self) -> typing.Optional[int]: 287 return self._client_id 288 289 @property 290 def metadata(self) -> collections.MutableMapping[typing.Any, typing.Any]: 291 """Pool's Metadata. This is different from client instance metadata.""" 292 return self._metadata 293 294 @typing.final 295 def acquire(self) -> RESTClient: 296 """Acquires a new `RESTClient` instance from this REST pool. 297 298 Returns 299 ------- 300 `RESTClient` 301 An instance of a REST client. 302 """ 303 return RESTClient( 304 self._token, 305 client_secret=self._client_secret, 306 client_id=self._client_id, 307 max_retries=self._max_retries, 308 enable_debugging=self._enable_debug, 309 client_session=self._client_session, 310 )
Pool of RESTClient instances.
This allows to create multiple instances of RESTClients that can be acquired
which share the same config and metadata.
Example
import aiobungie
import asyncio
client_pool = aiobungie.RESTPool("token", client_id=1234, client_secret='secret')
# Using a context manager to acquire an instance
# of the pool and close the connection after finishing.
async def first() -> str:
async with client_pool.acquire() as client:
return client.build_oauth2_url()
async def second() -> None:
async with client_pool.acquire() as client:
new_tokens = await client.refresh_access_token("token")
client.metadata['tokens'] = new_tokens
# Client instances are independent from first and second.
await asyncio.gather(first(), second())
Parameters
- token (
str): A valid application token from Bungie's developer portal.
Other Parameters
- max_retries (
int): The max retries number to retry if the request hit a5xxstatus code. - client_secret (
typing.Optional[str]): An optional application client secret, This is only needed if you're fetching OAuth2 tokens with this client. - client_id (
typing.Optional[int]): An optional application client id, This is only needed if you're fetching OAuth2 tokens with this client. - enable_debugging (
bool | str): Whether to enable logging responses or not.
Logging Levels
False: This will disable logging.True: This will set the level toDEBUGand enable logging minimal information. Like the response status, route, taken time and so on."TRACE" | TRACE: This will log the response headers along with the minimal information.
266 def __init__( 267 self, 268 token: str, 269 /, 270 *, 271 client_secret: typing.Optional[str] = None, 272 client_id: typing.Optional[int] = None, 273 client_session: typing.Optional[aiohttp.ClientSession] = None, 274 max_retries: int = 4, 275 enable_debugging: typing.Union[typing.Literal["TRACE"], bool, int] = False, 276 ) -> None: 277 self._client_secret = client_secret 278 self._client_id = client_id 279 self._token: str = token 280 self._max_retries = max_retries 281 self._metadata: collections.MutableMapping[typing.Any, typing.Any] = {} 282 self._enable_debug = enable_debugging 283 self._client_session = client_session
Pool's Metadata. This is different from client instance metadata.
294 @typing.final 295 def acquire(self) -> RESTClient: 296 """Acquires a new `RESTClient` instance from this REST pool. 297 298 Returns 299 ------- 300 `RESTClient` 301 An instance of a REST client. 302 """ 303 return RESTClient( 304 self._token, 305 client_secret=self._client_secret, 306 client_id=self._client_id, 307 max_retries=self._max_retries, 308 enable_debugging=self._enable_debug, 309 client_session=self._client_session, 310 )
Acquires a new RESTClient instance from this REST pool.
Returns
RESTClient: An instance of a REST client.
485@typing.final 486class Race(int, Enum): 487 """An Enum for Destiny races.""" 488 489 HUMAN = 0 490 AWOKEN = 1 491 EXO = 2 492 UNKNOWN = 3
An Enum for Destiny races.
133@typing.final 134class Raid(int, Enum): 135 """An Enum for all available raids in Destiny 2.""" 136 137 DSC = 910380154 138 """Deep Stone Crypt""" 139 140 LW = 2122313384 141 """Last Wish""" 142 143 VOG = 3881495763 144 """Normal Valut of Glass""" 145 146 GOS = 3458480158 147 """Garden Of Salvation"""
An Enum for all available raids in Destiny 2.
253@attrs.define(auto_exc=True) 254class RateLimitedError(HTTPError): 255 """Raised when too many request status code is returned.""" 256 257 http_status: http.HTTPStatus = attrs.field( 258 default=http.HTTPStatus.TOO_MANY_REQUESTS, init=False 259 ) 260 """The request response http status.""" 261 262 url: typedefs.StrOrURL 263 """The URL/endpoint caused this error.""" 264 265 body: typing.Any 266 """The response body.""" 267 268 retry_after: float = attrs.field(default=0.0) 269 """The amount of seconds you need to wait before retrying to requests.""" 270 271 message: str = attrs.field(init=False) 272 """A Bungie human readable message describes the cause of the error.""" 273 274 @message.default # type: ignore 275 def _(self) -> str: 276 return f"You're ratelimited for {self.retry_after}, Endpoint: {self.url}. Slow down!" 277 278 def __str__(self) -> str: 279 return self.message
Raised when too many request status code is returned.
2def __init__(self, url, body, retry_after=attr_dict['retry_after'].default): 3 self.http_status = attr_dict['http_status'].default 4 self.url = url 5 self.body = body 6 self.retry_after = retry_after 7 self.message = __attr_factory_message(self) 8 BaseException.__init__(self, self.url,self.body,self.retry_after)
Method generated by attrs for class RateLimitedError.
Inherited Members
- builtins.BaseException
- with_traceback
- args
48@typing.final 49class RecordState(enums.Flag): 50 """An enum for records component states.""" 51 52 NONE = 0 53 REDEEMED = 1 << 0 54 UNAVAILABLE = 1 << 1 55 OBJECTIVE_NOT_COMPLETED = 1 << 2 56 OBSCURED = 1 << 3 57 INVISIBLE = 1 << 4 58 ENTITLEMENT_UNOWNED = 1 << 5 59 CAN_EQUIP_TITLE = 1 << 6
An enum for records component states.
680@typing.final 681class Relationship(int, Enum): 682 """An enum for bungie friends relationship types.""" 683 684 UNKNOWN = 0 685 FRIEND = 1 686 INCOMING_REQUEST = 2 687 OUTGOING_REQUEST = 3
An enum for bungie friends relationship types.
181class RequestMethod(str, enums.Enum): 182 """HTTP request methods enum.""" 183 184 GET = "GET" 185 """GET methods.""" 186 POST = "POST" 187 """POST methods.""" 188 PUT = "PUT" 189 """PUT methods.""" 190 PATCH = "PATCH" 191 """PATCH methods.""" 192 DELETE = "DELETE" 193 """DELETE methods"""
HTTP request methods enum.
Inherited Members
- builtins.str
- encode
- replace
- split
- rsplit
- join
- capitalize
- casefold
- title
- center
- count
- expandtabs
- find
- partition
- index
- ljust
- lower
- lstrip
- rfind
- rindex
- rjust
- rstrip
- rpartition
- splitlines
- strip
- swapcase
- translate
- upper
- startswith
- endswith
- removeprefix
- removesuffix
- isascii
- islower
- isupper
- istitle
- isspace
- isdecimal
- isdigit
- isnumeric
- isalpha
- isalnum
- isidentifier
- isprintable
- zfill
- format
- format_map
- maketrans
248@attrs.define(auto_exc=True) 249class ResponseError(HTTPException): 250 """Exception for other HTTP response errors."""
Exception for other HTTP response errors.
2def __init__(self, *, error_code, http_status, throttle_seconds, url, body, headers, message, error_status, message_data): 3 self.error_code = error_code 4 self.http_status = http_status 5 self.throttle_seconds = throttle_seconds 6 self.url = url 7 self.body = body 8 self.headers = headers 9 self.message = message 10 self.error_status = error_status 11 self.message_data = message_data 12 BaseException.__init__(self, self.error_code,self.http_status,self.throttle_seconds,self.url,self.body,self.headers,self.message,self.error_status,self.message_data)
Method generated by attrs for class ResponseError.
Inherited Members
- HTTPException
- error_code
- http_status
- throttle_seconds
- url
- body
- headers
- message
- error_status
- message_data
- builtins.BaseException
- with_traceback
- args
507@typing.final 508class Stat(int, Enum): 509 """An Enum for Destiny 2 character stats.""" 510 511 NONE = 0 512 MOBILITY = 2996146975 513 RESILIENCE = 392767087 514 RECOVERY = 1943323491 515 DISCIPLINE = 1735777505 516 INTELLECT = 144602215 517 STRENGTH = 4244567218 518 LIGHT_POWER = 1935470627
An Enum for Destiny 2 character stats.
622@typing.final 623class TierType(int, Enum): 624 """An enum for a Destiny 2 item tier type.""" 625 626 UNKNOWN = 0 627 CURRENCY = 1 628 BASIC = 2 629 COMMON = 3 630 RARE = 4 631 SUPERIOR = 5 632 EXOTIC = 6
An enum for a Destiny 2 item tier type.
732@typing.final 733class TransferStatus(Flag): 734 """An enum for items transfer statuses.""" 735 736 CAN_TRANSFER = 0 737 """The item can be transferred.""" 738 IS_EQUIPPED = 1 << 0 739 """You can't transfer since the item is equipped.""" 740 NOT_TRASNFERRABLE = 1 << 1 741 """This item can not be transferred.""" 742 COULD_BE_TRANSFERRED = 1 << 2 743 """You can transfer the item. But the place you're trying to put it at has no space for it."""
An enum for items transfer statuses.
You can transfer the item. But the place you're trying to put it at has no space for it.
33class UndefinedType: 34 """An `UNDEFINED` type.""" 35 36 __instance: typing.Optional[UndefinedType] = None 37 38 def __bool__(self) -> typing.Literal[False]: 39 return False 40 41 def __int__(self) -> typing.Literal[0]: 42 return 0 43 44 def __repr__(self) -> str: 45 return "UNDEFINED" 46 47 def __str__(self) -> str: 48 return "UNDEFINED" 49 50 def __new__(cls) -> UndefinedType: 51 if cls.__instance is None: 52 o = super().__new__(cls) 53 cls.__instance = o 54 return cls.__instance
An UNDEFINED type.
75@typing.final 76class ValueUIStyle(int, enums.Enum): 77 AUTOMATIC = 0 78 FRACTION = 1 79 CHECK_BOX = 2 80 PERCENTAGE = 3 81 DATETIME = 4 82 FRACTION_FLOAT = 5 83 INTEGER = 6 84 TIME_DURATION = 7 85 HIDDEN = 8 86 MULTIPLIER = 9 87 GREEN_PIPS = 10 88 RED_PIPS = 11 89 EXPLICIT_PERCENTAGE = 12 90 RAW_FLOAT = 13 91 LEVEL_AND_REWARD = 14
An enumeration.
230@typing.final 231class Vendor(int, Enum): 232 """An Enum for all available vendors in Destiny 2.""" 233 234 ZAVALA = 69482069 235 XUR = 2190858386 236 BANSHE = 672118013 237 SPIDER = 863940356 238 SHAXX = 3603221665 239 KADI = 529635856 240 """Postmaster exo.""" 241 YUNA = 1796504621 242 """Asia servers only.""" 243 EVERVERSE = 3361454721 244 AMANDA = 460529231 245 """Amanda holiday""" 246 CROW = 3611983588 247 HAWTHORNE = 3347378076 248 ADA1 = 350061650 249 DRIFTER = 248695599 250 IKORA = 1976548992 251 SAINT = 765357505 252 """Saint-14""" 253 ERIS_MORN = 1616085565 254 SHAW_HAWN = 1816541247 255 """COSMODROME Guy""" 256 VARIKS = 2531198101
An Enum for all available vendors in Destiny 2.
521@typing.final 522class WeaponType(int, Enum): 523 """Enums for The three Destiny Weapon Types""" 524 525 NONE = 0 526 KINETIC = 1498876634 527 ENERGY = 2465295065 528 POWER = 953998645
Enums for The three Destiny Weapon Types
559def into_iter( 560 iterable: collections.Iterable[Item], 561) -> Iterator[Item]: 562 """Transform an iterable into an flat iterator. 563 564 Example 565 ------- 566 ```py 567 sequence = [1,2,3] 568 for item in aiobungie.into_iter(sequence).reversed(): 569 print(item) 570 # 3 571 # 2 572 # 1 573 ``` 574 575 Parameters 576 ---------- 577 iterable: `typing.Iterable[Item]` 578 The iterable to convert. 579 580 Raises 581 ------ 582 `StopIteration` 583 If no elements are left in the iterator. 584 """ 585 return Iterator(iterable)
Transform an iterable into an flat iterator.
Example
sequence = [1,2,3]
for item in aiobungie.into_iter(sequence).reversed():
print(item)
# 3
# 2
# 1
Parameters
- iterable (
typing.Iterable[Item]): The iterable to convert.
Raises
StopIteration: If no elements are left in the iterator.
282async def raise_error(response: aiohttp.ClientResponse) -> AiobungieError: 283 """Generates and raise exceptions on error responses.""" 284 285 # Not a JSON response, raise immediately. 286 287 # Also Bungie sometimes get funky and return HTML instead of JSON when making an authorized 288 # request with a dummy access token. I can't really do anything about this.. 289 if response.content_type != "application/json": 290 return HTTPError( 291 f"Expected JSON content but got {response.content_type!s}, {response.real_url!s}", 292 http.HTTPStatus.UNSUPPORTED_MEDIA_TYPE, 293 ) 294 295 body = await response.json() 296 message: str = body.get("Message", "UNDEFINED_MESSAGE") 297 error_status: str = body.get("ErrorStatus", "UNDEFINED_ERROR_STATUS") 298 message_data: dict[str, str] = body.get("MessageData", {}) 299 throttle_seconds: int = body.get("ThrottleSeconds", 0) 300 error_code: int = body.get("ErrorCode", 0) 301 302 # Standard HTTP status. 303 if response.status == http.HTTPStatus.NOT_FOUND: 304 return NotFound( 305 message=message, 306 error_code=error_code, 307 throttle_seconds=throttle_seconds, 308 url=str(response.real_url), 309 body=body, 310 headers=response.headers, 311 error_status=error_status, 312 message_data=message_data, 313 ) 314 315 elif response.status == http.HTTPStatus.FORBIDDEN: 316 return Forbidden( 317 message=message, 318 error_code=error_code, 319 throttle_seconds=throttle_seconds, 320 url=str(response.real_url), 321 body=body, 322 headers=response.headers, 323 error_status=error_status, 324 message_data=message_data, 325 ) 326 327 elif response.status == http.HTTPStatus.UNAUTHORIZED: 328 return Unauthorized( 329 message=message, 330 error_code=error_code, 331 throttle_seconds=throttle_seconds, 332 url=str(response.real_url), 333 body=body, 334 headers=response.headers, 335 error_status=error_status, 336 message_data=message_data, 337 ) 338 339 elif response.status == http.HTTPStatus.BAD_REQUEST: 340 # Membership needs to be alone. 341 if error_status == "InvalidParameters": 342 return MembershipTypeError( 343 message=message, 344 body=body, 345 headers=response.headers, 346 url=str(response.url), 347 membership_type=message_data["membershipType"], 348 required_membership=message_data["membershipInfo.membershipType"], 349 membership_id=int(message_data["membershipId"]), 350 ) 351 return BadRequest( 352 message=message, 353 body=body, 354 headers=response.headers, 355 url=str(response.url), 356 ) 357 358 status = http.HTTPStatus(response.status) 359 360 if 400 <= status < 500: 361 return ResponseError( 362 message=message, 363 error_code=error_code, 364 throttle_seconds=throttle_seconds, 365 url=str(response.real_url), 366 body=body, 367 headers=response.headers, 368 error_status=error_status, 369 message_data=message_data, 370 http_status=status, 371 ) 372 373 # Need to self handle ~5xx errors 374 elif 500 <= status < 600: 375 # No API key or method requires OAuth2 most likely. 376 if error_status in { 377 "ApiKeyMissingFromRequest", 378 "WebAuthRequired", 379 "ApiInvalidOrExpiredKey", 380 "AuthenticationInvalid", 381 "AuthorizationCodeInvalid", 382 }: 383 return Unauthorized( 384 message=message, 385 error_code=error_code, 386 throttle_seconds=throttle_seconds, 387 url=str(response.real_url), 388 body=body, 389 headers=response.headers, 390 error_status=error_status, 391 message_data=message_data, 392 ) 393 394 # Anything contains not found. 395 elif ( 396 "NotFound" in error_status or error_status == "UserCannotFindRequestedUser" 397 ): 398 return NotFound( 399 message=message, 400 error_code=error_code, 401 throttle_seconds=throttle_seconds, 402 url=str(response.real_url), 403 body=body, 404 headers=response.headers, 405 error_status=error_status, 406 message_data=message_data, 407 ) 408 409 # Other 5xx errors. 410 else: 411 return InternalServerError( 412 message=message, 413 error_code=error_code, 414 throttle_seconds=throttle_seconds, 415 url=str(response.real_url), 416 body=body, 417 headers=response.headers, 418 error_status=error_status, 419 message_data=message_data, 420 http_status=status, 421 ) 422 # Something else. 423 else: 424 return HTTPException( 425 message=message, 426 error_code=error_code, 427 throttle_seconds=throttle_seconds, 428 url=str(response.real_url), 429 body=body, 430 headers=response.headers, 431 error_status=error_status, 432 message_data=message_data, 433 http_status=status, 434 )
Generates and raise exceptions on error responses.
437def stringify_http_message(headers: collections.Mapping[str, str]) -> str: 438 return ( 439 "{ \n" 440 + "\n".join( # noqa: W503 441 f"{f' {key}'}: {value}" 442 if key not in ("Authorization", "X-API-KEY") 443 else f" {key}: HIDDEN_TOKEN" 444 for key, value in headers.items() 445 ) 446 + "\n}" # noqa: W503 447 )